This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
egcs-971105 MT-safe exception diffs
- To: egcs at cygnus dot com
- Subject: egcs-971105 MT-safe exception diffs
- From: Teemu Torma <tot at trema dot com>
- Date: Mon, 10 Nov 1997 14:59:57 +0100
- Organization: Trema Laboratories SARL
If someone is interested, here are updated MT-safe exception diffs
for pthreads and Solaris threads. I have tested these changes only
on sparc-sun-solaris2.5.1.
cp/except.c diffs are quite small now, thanks to nested exception
handling.
I have not had time to get thread specifics out from libgcc2.
Actually I had to add more to implement locking in frame.c.
I removed the usage `top_elt' in libgcc2, using a zero pointer
instead. I don't know if this has any undesired side-effects,
at least quick testing shows that sjlj-exceptions still work.
Teemu
ChangeLog:
1997-11-10 Teemu Torma <tot@trema.com>
* frame.c: Define macros OBJECT_LOCK() and OBJECT_UNLOCK()
to lock the mutex protecting object list.
(find_fde, __register_frame, __register_frame_table,
__deregister_frame): Hold the lock while accessing objects.
1997-11-06 Teemu Torma <tot@trema.com>
* config/sparc/t-sol2: Added multilibs for -threads and
made -pthreads alias to it.
* config/sparc/sol2.h (CPP_SPEC, LIB_SPEC):
Added -threads and -pthreads options.
* libgcc2.c: Thread support for pthreads and Solaris threads.
* libgcc2.c: (__get_cpp_eh_context): Removed.
(struct cpp_eh_context): Removed.
(struct eh_context): Replaced cpp_eh_context with generic language
specific pointer.
(__get_eh_info): New function.
(__throw): Check eh_context::info.
(__sjthrow): Ditto.
* libgcc2.c (new_eh_context, __get_eh_context,
eh_pthread_initialize, eh_context_initialize, eh_context_static,
eh_context_per_thread, eh_context_free): New functions.
(get_eh_context, eh_context_key): New variables.
(__sjthrow, __sjpopnthrow, __eh_pcnthrow, __throw): Use
get_eh_context to get the context.
* except.c (get_dynamic_handler_chain): Use get_eh_context_libfunc
to get EH context.
(get_saved_pc_ref): Ditto.
* optabs.c (get_eh_context_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_eh_context_libfunc.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* libgcc2.c (cpp_eh_context, __get_cpp_eh_context,
__get_saved_pc): New.
(__eh_type, __eh_pc): Deleted.
(__sjthrow): Use __get_cpp_eh_context()->type instead of
__eh_type.
(__eh_pcnthrow): Use __get_saved_pc() instead of __eh_pc.
(__get_dynamic_handler_chain): Move __dynamic_handler_chain inside
this fcn.
* except.c (get_saved_pc_ref): New functions.
(eh_saved_pc_rtx, eh_saved_pc): Deleted.
(expand_internal_throw_indirect): Use get_saved_pc_ref() instead
of eh_saved_pc.
(end_eh_unwinder): Likewise.
(init_eh): Remove initialization of eh_saved_pc.
* optabs.c (get_saved_pc_libfunc): New variable.
(init_optabs): Initialize it.
* expr.h: Declare get_saved_pc_libfunc.
* except.h (eh_saved_pc_rtx): Deleted.
(get_saved_pc_ref): Declared.
cp/ChangeLog:
1997-11-06 Teemu Torma <tot@trema.com>
* exception.cc (__cp_exception_info): Use __get_eh_info.
(__cp_push_exception): Ditto.
(__cp_pop_exception): Ditto.
From Scott Snyder <snyder@d0sgif.fnal.gov>:
* except.c (expand_builtin_throw): Use get_saved_pc_ref instead of
saved_pc.
(init_exception_processing): Removed saved_pc initialization.
Index: except.c
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/except.c,v
retrieving revision 1.1.1.4
retrieving revision 1.5
diff -u -u -p -r1.1.1.4 -r1.5
--- except.c 1997/11/06 11:53:52 1.1.1.4
+++ except.c 1997/11/06 13:35:13 1.5
@@ -494,11 +494,6 @@ struct label_node *caught_return_label_s
struct label_node *false_label_stack = NULL;
-/* The rtx and the tree for the saved PC value. */
-
-rtx eh_saved_pc_rtx;
-tree eh_saved_pc;
-
rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx));
/* Various support routines to manipulate the various data structures
@@ -750,10 +745,14 @@ get_dynamic_handler_chain ()
emit_insns_before (insns, get_first_nonparm_insn ());
}
#else
+ rtx ehc;
rtx dhc;
- dhc = emit_library_call_value (get_dynamic_handler_chain_libfunc,
+
+ ehc = emit_library_call_value (get_eh_context_libfunc,
NULL_RTX, 1,
Pmode, 0);
+ /* dhc is at the beginnig of the returned structure. */
+ dhc = ehc;
current_function_dhc = copy_to_reg (dhc);
#endif
@@ -781,6 +780,27 @@ get_dynamic_cleanup_chain ()
return gen_rtx (MEM, Pmode, current_function_dcc);
}
+/* Get a reference to the saved_pc variable.
+
+ FIXME: When get_dynamic_handler_chain() is fixed to only make the libcall
+ once per function, this should be fixed in the same way. */
+
+rtx
+get_saved_pc_ref ()
+{
+ rtx ehc, ehpc, current_function_ehpc;
+
+ /* Saved PC is the second word into the returned structure. */
+ ehc = emit_library_call_value (get_eh_context_libfunc,
+ NULL_RTX, 1,
+ Pmode, 0);
+ ehpc = plus_constant (ehc, GET_MODE_SIZE (Pmode));
+ current_function_ehpc = copy_to_reg (ehpc);
+
+ /* We don't want a copy of the ehpc, but rather, the single ehpc. */
+ return gen_rtx (MEM, Pmode, current_function_ehpc);
+}
+
/* Generate code to evaluate X and jump to LABEL if the value is nonzero.
LABEL is an rtx of code CODE_LABEL, in this function. */
@@ -1158,8 +1178,7 @@ static void
expand_internal_throw_indirect (context)
rtx context;
{
- assemble_external (eh_saved_pc);
- emit_move_insn (eh_saved_pc_rtx, context);
+ emit_move_insn (get_saved_pc_ref (), context);
emit_throw ();
}
@@ -1647,8 +1666,6 @@ end_eh_unwinder ()
return;
#else /* DWARF2_UNWIND_INFO */
- assemble_external (eh_saved_pc);
-
expr = make_node (RTL_EXPR);
TREE_TYPE (expr) = void_type_node;
RTL_EXPR_RTL (expr) = const0_rtx;
@@ -1666,7 +1683,7 @@ end_eh_unwinder ()
return_val_rtx = eh_outer_context (return_val_rtx);
return_val_rtx = expand_binop (Pmode, sub_optab, return_val_rtx, GEN_INT (1),
NULL_RTX, 0, OPTAB_LIB_WIDEN);
- emit_move_insn (eh_saved_pc_rtx, return_val_rtx);
+ emit_move_insn (get_saved_pc_ref (), return_val_rtx);
/* Either set things up so we do a return directly to __throw, or
we return here instead. */
@@ -1926,12 +1943,6 @@ init_eh ()
/* Generate rtl to reference the variable in which the PC of the
current context is saved. */
tree type = build_pointer_type (make_node (VOID_TYPE));
-
- eh_saved_pc = build_decl (VAR_DECL, get_identifier ("__eh_pc"), type);
- DECL_EXTERNAL (eh_saved_pc) = 1;
- TREE_PUBLIC (eh_saved_pc) = 1;
- make_decl_rtl (eh_saved_pc, NULL_PTR, 1);
- eh_saved_pc_rtx = DECL_RTL (eh_saved_pc);
}
/* Initialize the per-function EH information. */
Index: except.h
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/except.h,v
retrieving revision 1.1.1.2
retrieving revision 1.3
diff -u -u -p -r1.1.1.2 -r1.3
--- except.h 1997/10/01 13:14:26 1.1.1.2
+++ except.h 1997/10/01 13:58:27 1.3
@@ -246,10 +246,6 @@ extern struct label_node *false_label_st
extern rtx exception_handler_labels;
-/* The rtx for the saved PC value. */
-
-extern rtx eh_saved_pc_rtx;
-
/* Performs optimizations for exception handling, such as removing
unnecessary exception regions. Invoked from jump_optimize (). */
@@ -260,6 +256,9 @@ extern rtx get_dynamic_handler_chain PR
/* Get the dynamic cleanup chain. */
extern rtx get_dynamic_cleanup_chain PROTO((void));
+
+/* Get the saved PC variable. */
+extern rtx get_saved_pc_ref PROTO((void));
/* Throw an exception. */
Index: expr.h
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/expr.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -u -p -r1.1.1.1 -r1.2
--- expr.h 1997/09/26 09:56:56 1.1.1.1
+++ expr.h 1997/09/26 15:43:10 1.2
@@ -417,6 +417,8 @@ extern rtx terminate_libfunc;
extern rtx setjmp_libfunc;
extern rtx longjmp_libfunc;
extern rtx get_dynamic_handler_chain_libfunc;
+extern rtx get_saved_pc_libfunc;
+extern rtx get_eh_context_libfunc;
extern rtx eqhf2_libfunc;
extern rtx nehf2_libfunc;
Index: frame.c
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/frame.c,v
retrieving revision 1.1.1.3
retrieving revision 1.5
diff -u -u -p -r1.1.1.3 -r1.5
--- frame.c 1997/11/03 09:01:23 1.1.1.3
+++ frame.c 1997/11/10 13:26:34 1.5
@@ -39,6 +39,27 @@ Boston, MA 02111-1307, USA. */
#include "frame.h"
#include <stddef.h>
+#if _PTHREADS
+
+#include <pthread.h>
+static pthread_mutex_t object_mutex = PTHREAD_MUTEX_INITIALIZER;
+#define OBJECT_LOCK() (pthread_mutex_lock (&object_mutex) != -1)
+#define OBJECT_UNLOCK() (pthread_mutex_unlock (&object_mutex) != -1)
+
+#elif _SOLARIS_THREADS
+
+#include <thread.h>
+static mutex_t object_mutex;
+#define OBJECT_LOCK() (mutex_lock (&object_mutex) != -1)
+#define OBJECT_UNLOCK() (mutex_unlock (&object_mutex) != -1)
+
+#else /* no threads */
+
+#define OBJECT_LOCK() (0)
+#define OBJECT_UNLOCK() (0)
+
+#endif /* no threads */
+
/* Don't use `fancy_abort' here even if config.h says to use it. */
#ifdef abort
#undef abort
@@ -220,7 +241,9 @@ count_fdes (fde *this_fde)
for (count = 0; this_fde->length != 0; this_fde = next_fde (this_fde))
{
/* Skip CIEs and linked once FDE entries. */
- if (this_fde->CIE_delta == 0 || this_fde->pc_range == 0)
+ if (this_fde->CIE_delta == 0
+ || this_fde->pc_range == 0
+ || this_fde->pc_begin == 0)
continue;
++count;
@@ -240,7 +263,9 @@ add_fdes (fde *this_fde, fde **array, si
for (; this_fde->length != 0; this_fde = next_fde (this_fde))
{
/* Skip CIEs and linked once FDE entries. */
- if (this_fde->CIE_delta == 0 || this_fde->pc_range == 0)
+ if (this_fde->CIE_delta == 0
+ || this_fde->pc_range == 0
+ || this_fde->pc_begin == 0)
continue;
fde_insert (array, i++, this_fde);
@@ -306,6 +331,8 @@ find_fde (void *pc)
struct object *ob;
size_t lo, hi;
+ OBJECT_LOCK ();
+
for (ob = objects; ob; ob = ob->next)
{
if (ob->pc_begin == 0)
@@ -314,6 +341,8 @@ find_fde (void *pc)
break;
}
+ OBJECT_UNLOCK ();
+
if (ob == 0)
return 0;
@@ -521,8 +550,12 @@ __register_frame (void *begin)
ob->fde_array = 0;
ob->count = 0;
+ OBJECT_LOCK ();
+
ob->next = objects;
objects = ob;
+
+ OBJECT_UNLOCK ();
}
/* Similar, but BEGIN is actually a pointer to a table of unwind entries
@@ -540,8 +573,12 @@ __register_frame_table (void *begin)
ob->pc_begin = ob->pc_end = 0;
ob->count = 0;
+ OBJECT_LOCK ();
+
ob->next = objects;
objects = ob;
+
+ OBJECT_UNLOCK ();
}
/* Called from crtend.o to deregister the unwind info for an object. */
@@ -549,8 +586,11 @@ __register_frame_table (void *begin)
void
__deregister_frame (void *begin)
{
- struct object **p = &objects;
+ struct object **p;
+
+ OBJECT_LOCK ();
+ p = &objects;
while (*p)
{
if ((*p)->fde_begin == begin)
@@ -563,10 +603,13 @@ __deregister_frame (void *begin)
free (ob->fde_array);
free (ob);
+ OBJECT_UNLOCK ();
return;
}
p = &((*p)->next);
}
+
+ OBJECT_UNLOCK ();
abort ();
}
Index: libgcc2.c
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/libgcc2.c,v
retrieving revision 1.1.1.4
retrieving revision 1.8
diff -u -u -p -r1.1.1.4 -r1.8
--- libgcc2.c 1997/11/06 11:54:19 1.1.1.4
+++ libgcc2.c 1997/11/10 13:04:29 1.8
@@ -3109,10 +3109,6 @@ int _exit_dummy_decl = 0; /* prevent com
/* Shared exception handling support routines. */
-/* Language-specific information about the active exception(s). If there
- are no active exceptions, it is set to 0. */
-void *__eh_info;
-
void
__default_terminate ()
{
@@ -3144,6 +3140,210 @@ __empty ()
{
}
+/* EH context structure. */
+
+struct eh_context
+{
+ void **dynamic_handler_chain;
+ void *saved_pc;
+#ifndef DWARF2_UNWIND_INFO
+ void *buf[2];
+#endif
+ /* This is language dependent part of the eh context. */
+ void *info;
+};
+
+/* Allocate and return a new EH context structure. */
+
+extern void __throw ();
+
+static void *
+new_eh_context ()
+{
+ struct eh_context *eh = (struct eh_context *) malloc (sizeof *eh);
+ if (! eh)
+ __terminate ();
+
+ memset (eh, 0, sizeof *eh);
+
+ eh->dynamic_handler_chain = 0;
+#ifndef DWARF2_UNWIND_INFO
+ eh->buf[0] = &eh->saved_pc;
+ eh->buf[1] = &__throw;
+#endif
+
+ return eh;
+}
+
+/* Pointer to function to return EH context. */
+
+static struct eh_context *eh_context_initialize ();
+static struct eh_context *eh_context_static ();
+static struct eh_context *eh_context_per_thread ();
+
+static struct eh_context *(*get_eh_context) () = &eh_context_initialize;
+
+/* Thread specific key to get EH context. */
+#if _PTHREADS
+
+#include <pthread.h>
+
+static pthread_key_t eh_context_key;
+
+/* Destructor for struct eh_context. */
+static void
+eh_context_free (void *ptr)
+{
+ if (ptr)
+ free (ptr);
+}
+#else /* not _PTHREADS */
+#if _SOLARIS_THREADS
+
+#include <thread.h>
+
+static thread_key_t eh_context_key;
+
+/* Destructor for struct eh_context. */
+static void
+eh_context_free (void *ptr)
+{
+ if (ptr)
+ free (ptr);
+}
+#endif /* _SOLARIS_THREADS */
+#endif /* _PTHREADS */
+
+/* Routine to get EH context.
+ This one will simply call the function pointer. */
+
+void *
+__get_eh_context ()
+{
+ return (void *) (*get_eh_context) ();
+}
+
+/* Get and set the language specific info pointer. */
+
+void **
+__get_eh_info ()
+{
+ struct eh_context *eh = (*get_eh_context) ();
+ return (void **) &eh->info;
+}
+
+#if _PTHREADS
+static void
+eh_pthread_initialize ()
+{
+ /* Try to create the key. If it fails, revert to static method,
+ otherwise start using thread specific EH contexts. */
+ if (pthread_key_create (&eh_context_key, &eh_context_free) == 0)
+ get_eh_context = &eh_context_per_thread;
+ else
+ get_eh_context = &eh_context_static;
+}
+#endif
+
+/* Initialize EH context.
+ This will be called only once, since we change GET_EH_CONTEXT
+ pointer to another routine. */
+
+static struct eh_context *
+eh_context_initialize ()
+{
+#if _PTHREADS
+
+ static pthread_once_t initialized = PTHREAD_ONCE_INIT;
+ pthread_once (&initialized, eh_pthread_initialize);
+
+#else /* not _PTHREADS */
+#if _SOLARIS_THREADS
+
+ /* Mutex to make sure that we do not get initialized twice.
+ There is no need to call mutex_init; we do not need
+ inter-process mutex. */
+ static mutex_t mutex;
+ mutex_lock (&mutex);
+
+ /* Verify that get_eh_context still points to us; another thread
+ may already have changed it. */
+ if (get_eh_context == &eh_context_initialize)
+ {
+ /* Try to create the key. If it fails, revert to static method,
+ otherwise start using thread specific EH contexts. */
+ if (thr_keycreate (&eh_context_key, &eh_context_free) == 0)
+ get_eh_context = &eh_context_per_thread;
+ else
+ get_eh_context = &eh_context_static;
+ }
+ mutex_unlock (&mutex);
+
+#else /* not _SOLARIS_THREADS */
+
+ /* Use static version of EH context. */
+ get_eh_context = &eh_context_static;
+
+#endif /* not _SOLARIS_THREADS */
+#endif /* not _PTHREADS */
+
+ return (*get_eh_context) ();
+}
+
+/* Return a static EH context. */
+
+static struct eh_context *
+eh_context_static ()
+{
+ static struct eh_context *eh;
+ if (! eh)
+ eh = new_eh_context ();
+ return eh;
+}
+
+/* Return a thread specific EH context. */
+
+static struct eh_context *
+eh_context_per_thread ()
+{
+ struct eh_context *eh;
+
+#if _PTHREADS
+
+ eh = (struct eh_context *) pthread_getspecific (eh_context_key);
+ if (! eh)
+ {
+ eh = new_eh_context ();
+ if (pthread_setspecific (eh_context_key, (void *) eh) != 0)
+ __terminate ();
+ }
+
+#else /* not _PTHREADS */
+#if _SOLARIS_THREADS
+
+ {
+ void *eh_ptr;
+ if (thr_getspecific (eh_context_key, &eh_ptr) != 0)
+ __terminate ();
+ eh = (struct eh_context *) eh_ptr;
+ if (! eh)
+ {
+ eh = new_eh_context ();
+ if (thr_setspecific (eh_context_key, (void *) eh) != 0)
+ __terminate ();
+ }
+ }
+
+#else /* not _SOLARIS_THREADS */
+
+ __terminate ();
+
+#endif /* not _SOLARIS_THREADS */
+#endif /* not _PTHREADS */
+
+ return eh;
+}
+
/* Support routines for setjmp/longjmp exception handling. */
/* Calls to __sjthrow are generated by the compiler when an exception
@@ -3152,33 +3352,36 @@ __empty ()
extern void longjmp (void *, int);
-static void *top_elt[2];
-void **__dynamic_handler_chain = top_elt;
-
/* Routine to get the head of the current thread's dynamic handler chain
- use for exception handling.
-
- TODO: make thread safe. */
+ use for exception handling. */
void ***
__get_dynamic_handler_chain ()
{
- return &__dynamic_handler_chain;
+ struct eh_context *eh = (*get_eh_context) ();
+ return (void ***) &eh->dynamic_handler_chain;
+}
+
+void **
+__get_saved_pc ()
+{
+ struct eh_context *eh = (*get_eh_context) ();
+ return (void **) &eh->saved_pc;
}
/* This is used to throw an exception when the setjmp/longjmp codegen
method is used for exception handling.
- We call __terminate if there are no handlers left (we know this
- when the dynamic handler chain is top_elt). Otherwise we run the
- cleanup actions off the dynamic cleanup stack, and pop the top of
- the dynamic handler chain, and use longjmp to transfer back to the
- associated handler. */
+ We call __terminate if there are no handlers left. Otherwise we run the
+ cleanup actions off the dynamic cleanup stack, and pop the top of the
+ dynamic handler chain, and use longjmp to transfer back to the associated
+ handler. */
void
__sjthrow ()
{
- void ***dhc = __get_dynamic_handler_chain ();
+ struct eh_context *eh = (*get_eh_context) ();
+ void ***dhc = &eh->dynamic_handler_chain;
void *jmpbuf;
void (*func)(void *, int);
void *arg;
@@ -3226,7 +3429,7 @@ __sjthrow ()
/* We must call terminate if we try and rethrow an exception, when
there is no exception currently active and when there are no
handlers left. */
- if (! __eh_info || (*dhc) == top_elt)
+ if (! eh->info || (*dhc) == 0)
__terminate ();
/* Find the jmpbuf associated with the top element of the dynamic
@@ -3253,7 +3456,8 @@ __sjthrow ()
void
__sjpopnthrow ()
{
- void ***dhc = __get_dynamic_handler_chain ();
+ struct eh_context *eh = (*get_eh_context) ();
+ void ***dhc = &eh->dynamic_handler_chain;
void *jmpbuf;
void (*func)(void *, int);
void *arg;
@@ -3309,8 +3513,6 @@ __sjpopnthrow ()
/* This value identifies the place from which an exception is being
thrown. */
-void *__eh_pc;
-
#ifdef EH_TABLE_LOOKUP
EH_TABLE_LOOKUP
@@ -3433,11 +3635,8 @@ __throw ()
/* See expand_builtin_throw for details. */
void **__eh_pcnthrow () {
- static void *buf[2] = {
- &__eh_pc,
- &__throw
- };
- return buf;
+ struct eh_context *eh = (*get_eh_context) ();
+ return &eh->buf[0];
}
#if #machine(i386)
@@ -3644,6 +3843,7 @@ in_reg_window (int reg, frame_state *uda
void
__throw ()
{
+ struct eh_context *eh = (*get_eh_context) ();
void *pc, *handler, *retaddr;
frame_state ustruct, ustruct2;
frame_state *udata = &ustruct;
@@ -3654,7 +3854,7 @@ __throw ()
/* This is required for C++ semantics. We must call terminate if we
try and rethrow an exception, when there is no exception currently
active. */
- if (! __eh_info)
+ if (! eh->info)
__terminate ();
/* Start at our stack frame. */
@@ -3679,7 +3879,7 @@ label:
__builtin_unwind_init ();
/* Now reset pc to the right throw point. */
- pc = __eh_pc;
+ pc = eh->saved_pc;
for (;;)
{
@@ -3710,7 +3910,7 @@ label:
if (! handler)
__terminate ();
- if (pc == __eh_pc)
+ if (pc == eh->saved_pc)
/* We found a handler in the throw context, no need to unwind. */
udata = my_udata;
else
@@ -3725,7 +3925,7 @@ label:
void *handler_pc = pc;
/* Start from the throw context again. */
- pc = __eh_pc;
+ pc = eh->saved_pc;
memcpy (udata, my_udata, sizeof (*udata));
while (pc != handler_pc)
Index: optabs.c
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/optabs.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -u -p -r1.1.1.1 -r1.2
--- optabs.c 1997/09/26 09:57:06 1.1.1.1
+++ optabs.c 1997/09/26 15:43:12 1.2
@@ -125,6 +125,8 @@ rtx terminate_libfunc;
rtx setjmp_libfunc;
rtx longjmp_libfunc;
rtx get_dynamic_handler_chain_libfunc;
+rtx get_saved_pc_libfunc;
+rtx get_eh_context_libfunc;
rtx eqhf2_libfunc;
rtx nehf2_libfunc;
@@ -4290,6 +4292,8 @@ init_optabs ()
longjmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "longjmp");
#endif
get_dynamic_handler_chain_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__get_dynamic_handler_chain");
+ get_saved_pc_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__get_saved_pc");
+ get_eh_context_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__get_eh_context");
eqhf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqhf2");
nehf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nehf2");
Index: config/sparc/sol2.h
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/config/sparc/sol2.h,v
retrieving revision 1.1.1.2
retrieving revision 1.6
diff -u -u -p -r1.1.1.2 -r1.6
--- sol2.h 1997/10/24 09:12:33 1.1.1.2
+++ sol2.h 1997/11/10 12:11:04 1.6
@@ -30,6 +30,8 @@ Boston, MA 02111-1307, USA. */
#undef CPP_SUBTARGET_SPEC
#define CPP_SUBTARGET_SPEC "\
+%{pthreads:-D_REENTRANT -D_PTHREADS} \
+%{!pthreads:%{threads:-D_REENTRANT -D_SOLARIS_THREADS}} \
%{compat-bsd:-iwithprefixbefore ucbinclude -I/usr/ucbinclude} \
"
@@ -131,7 +133,12 @@ Boston, MA 02111-1307, USA. */
#undef LIB_SPEC
#define LIB_SPEC \
- "%{compat-bsd:-lucb -lsocket -lnsl -lelf -laio} %{!shared:%{!symbolic:-lc}}"
+ "%{compat-bsd:-lucb -lsocket -lnsl -lelf -laio} \
+ %{!shared:\
+ %{!symbolic:\
+ %{pthreads:-lpthread} \
+ %{!pthreads:%{threads:-lthread}} \
+ -lc}}"
#undef ENDFILE_SPEC
#define ENDFILE_SPEC "crtend.o%s crtn.o%s"
Index: config/sparc/t-sol2
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/config/sparc/t-sol2,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -u -p -r1.1.1.1 -r1.3
--- t-sol2 1997/09/26 09:58:14 1.1.1.1
+++ t-sol2 1997/10/09 09:18:59 1.3
@@ -5,6 +5,13 @@ LIBGCC1 =
CROSS_LIBGCC1 =
LIBGCC1_TEST =
+MULTILIB_OPTIONS = threads
+MULTILIB_DIRNAMES = threads
+MULTILIB_MATCHES = threads=pthreads
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
# gmon build rule:
gmon.o: $(srcdir)/config/sparc/gmon-sol2.c $(GCC_PASSES) $(CONFIG_H) stmp-int-hdrs
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
Index: cp/except.c
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/cp/except.c,v
retrieving revision 1.1.1.4
retrieving revision 1.4
diff -u -u -p -r1.1.1.4 -r1.4
--- except.c 1997/11/06 11:58:06 1.1.1.4
+++ except.c 1997/11/06 13:35:17 1.4
@@ -192,9 +192,6 @@ static tree TerminateFunctionCall;
========================================================================= */
-/* Holds the pc for doing "throw" */
-static tree saved_pc;
-
extern int throw_used;
extern rtx catch_clauses;
@@ -294,13 +291,6 @@ init_exception_processing ()
pop_lang_context ();
- d = build_decl (VAR_DECL, get_identifier ("__eh_pc"), ptr_type_node);
- TREE_PUBLIC (d) = 1;
- DECL_EXTERNAL (d) = 1;
- DECL_ARTIFICIAL (d) = 1;
- cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
- saved_pc = d;
-
/* If we use setjmp/longjmp EH, arrange for all cleanup actions to
be protected with __terminate. */
protect_cleanup_actions_with_terminate = 1;
@@ -821,8 +811,10 @@ expand_builtin_throw ()
/* search for an exception handler for the saved_pc */
handler = do_function_call (FirstExceptionMatch,
- expr_tree_cons (NULL_TREE, saved_pc,
- NULL_TREE),
+ expr_tree_cons (NULL_TREE,
+ make_tree (ptr_ptr_type_node,
+ get_saved_pc_ref ()),
+ NULL_TREE),
ptr_type_node);
assemble_external (TREE_OPERAND (FirstExceptionMatch, 0));
@@ -902,7 +894,7 @@ expand_builtin_throw ()
}
else
#endif
- emit_move_insn (eh_saved_pc_rtx, next_pc);
+ emit_move_insn (get_saved_pc_ref (), next_pc);
after_unwind = gen_label_rtx ();
do_unwind (gen_rtx (LABEL_REF, Pmode, after_unwind));
Index: cp/exception.cc
===================================================================
RCS file: /trema/cvs/gnu/egcs/gcc/cp/exception.cc,v
retrieving revision 1.1.1.2
retrieving revision 1.4
diff -u -u -p -r1.1.1.2 -r1.4
--- exception.cc 1997/11/06 11:58:07 1.1.1.2
+++ exception.cc 1997/11/07 09:21:03 1.4
@@ -85,9 +85,9 @@ struct cp_eh_info
cp_eh_info *next;
};
-/* Language-specific EH info pointer, defined in libgcc2. */
+/* Language-specific EH info pointer, defined in libgcc2. */
-extern cp_eh_info *__eh_info; // actually void*
+extern "C" cp_eh_info **__get_eh_info (); // actually void **
/* Is P the type_info node for a pointer of some kind? */
@@ -99,7 +99,7 @@ extern bool __is_pointer (void *);
extern "C" cp_eh_info *
__cp_exception_info (void)
{
- return __eh_info;
+ return *__get_eh_info ();
}
/* Compiler hook to push a new exception onto the stack.
@@ -113,8 +113,11 @@ __cp_push_exception (void *value, void *
p->type = type;
p->cleanup = cleanup;
p->caught = false;
- p->next = __eh_info;
- __eh_info = p;
+
+ cp_eh_info *&eh_info = *__get_eh_info ();
+
+ p->next = eh_info;
+ eh_info = p;
}
/* Compiler hook to pop an exception that has been finalized. Used by
@@ -123,7 +126,7 @@ __cp_push_exception (void *value, void *
extern "C" void
__cp_pop_exception (void)
{
- cp_eh_info *p = __eh_info;
+ cp_eh_info *&p = *__get_eh_info ();
if (p->cleanup)
/* 3 is a magic value for destructors; see build_delete(). */
@@ -133,7 +136,7 @@ __cp_pop_exception (void)
else
delete p->value;
- __eh_info = p->next;
+ p = p->next;
delete p;
}