[m-rev.] for review: thread safe exceptions
Peter Ross
pro at missioncriticalit.com
Fri Feb 28 07:35:57 AEDT 2003
Hi,
===================================================================
Estimated hours taken: 4
Branches: main, release
Get exceptions working in the parallel grades.
library/exception.m:
Store the exception handler of a thread in thread local
storage when compiling in a parallel grade.
Index: 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
--- exception.m 25 Nov 2002 00:27:32 -0000 1.72.2.1
+++ exception.m 27 Feb 2003 20:31:26 -0000
@@ -777,25 +777,36 @@
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;
+#ifdef MR_THREAD_SAFE
+ MercuryThreadKey ML_exception_handler_key;
+#else
+ ML_ExceptionHandler *ML_exception_handler;
+#endif
+
+#ifdef MR_THREAD_SAFE
+ #define ML_GET_EXCEPTION_HANDLER MR_GETSPECIFIC(ML_exception_handler_key)
+ #define ML_SET_EXCEPTION_HANDLER(val) \
+ pthread_setspecific(ML_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 +891,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 +902,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 +910,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 +925,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 +937,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 +946,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 +973,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 +982,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 +997,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 +1005,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 +1032,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 +1041,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 +1054,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 +1072,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 +1089,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),
@@ -2050,6 +2061,13 @@
void
mercury_sys_init_exceptions_init(void)
{
+#ifdef MR_THREAD_SAFE
+ if (MR_KEY_CREATE(&ML_exception_handler_key, NULL) != 0) {
+ MR_fatal_error(
+ ""Unable to create ML_exception_handler_key.\\n"");
+ }
+#endif
+
#ifndef MR_HIGHLEVEL_CODE
exceptions_module();
#endif
--------------------------------------------------------------------------
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