This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

egcs-971105 MT-safe exception diffs


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



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]