This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
EGCS-1.1.1 PATCH: hooks in libgcc(eh.o) [thread safety]
- To: egcs-patches at cygnus dot com
- Subject: EGCS-1.1.1 PATCH: hooks in libgcc(eh.o) [thread safety]
- From: Leon Bottou <leonb at research dot att dot com>
- Date: Thu, 26 Nov 1998 11:39:52 -0500
( now with a better subject line )
There are many cases where we want to use hand-made cooperative threads
- when the system does not provide threads,
- when we run in a .so file loaded by a non-threaded program
shared object (netscape plugins)
EGCS exceptions will not work in portable mode (-fsjlj-exceptions) with
cooperative threads because the exception handler chain gets mixed.
This is the only problem since there is no real need to lock data structures
with cooperative threads.
Here is a patch on libgcc2.c (release_1_1_1 branch) which exposes
the function __new_eh_context() and the pointer __get_eh_context_ptr.
A user program can now redirect __get_eh_context_ptr to a custom
function which will properly create a __new_eh_context() per cooperative
thread and return the right eh context pointer. There is no need
to write a custom gthr-my-own-threads.h or to recompile libgcc.a.
The changes consist of:
- removing a two "static" keywords
- renaming the corresponding function/pointer with a double underscore prefix.
- propagating the new names where needed.
Is this patch acceptable ?
- Leon Bottou.
Index: libgcc2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/libgcc2.c,v
retrieving revision 1.46.2.1
diff -c -r1.46.2.1 libgcc2.c
*** libgcc2.c 1998/11/23 20:37:20 1.46.2.1
--- libgcc2.c 1998/11/25 21:32:34
***************
*** 3063,3071 ****
extern void __throw ();
! static void *
! new_eh_context ()
{
struct eh_full_context {
struct eh_context c;
void *top_elt[2];
--- 3063,3073 ----
extern void __throw ();
! void *
! __new_eh_context ()
{
+ /* This function is externally visible so that user programs may call it.
+ This is useful when a program uses non-system cooperative threads. */
struct eh_full_context {
struct eh_context c;
void *top_elt[2];
***************
*** 3101,3107 ****
}
#endif
! /* Pointer to function to return EH context. */
static struct eh_context *eh_context_initialize ();
static struct eh_context *eh_context_static ();
--- 3103,3111 ----
}
#endif
! /* Pointer to function to return EH context.
! This pointer is external so that user programs can modify
! it in order to adapt to any hand-made cooperative threads. */
static struct eh_context *eh_context_initialize ();
static struct eh_context *eh_context_static ();
***************
*** 3109,3115 ****
static struct eh_context *eh_context_specific ();
#endif
! static struct eh_context *(*get_eh_context) () = &eh_context_initialize;
/* Routine to get EH context.
This one will simply call the function pointer. */
--- 3113,3119 ----
static struct eh_context *eh_context_specific ();
#endif
! struct eh_context *(*__get_eh_context_ptr) () = &eh_context_initialize;
/* Routine to get EH context.
This one will simply call the function pointer. */
***************
*** 3117,3123 ****
void *
__get_eh_context ()
{
! return (void *) (*get_eh_context) ();
}
/* Get and set the language specific info pointer. */
--- 3121,3127 ----
void *
__get_eh_context ()
{
! return (void *) (*__get_eh_context_ptr) ();
}
/* Get and set the language specific info pointer. */
***************
*** 3125,3131 ****
void **
__get_eh_info ()
{
! struct eh_context *eh = (*get_eh_context) ();
return &eh->info;
}
--- 3129,3135 ----
void **
__get_eh_info ()
{
! struct eh_context *eh = (*__get_eh_context_ptr) ();
return &eh->info;
}
***************
*** 3136,3149 ****
/* Try to create the key. If it fails, revert to static method,
otherwise start using thread specific EH contexts. */
if (__gthread_key_create (&eh_context_key, &eh_context_free) == 0)
! get_eh_context = &eh_context_specific;
else
! get_eh_context = &eh_context_static;
}
#endif /* no __GTHREADS */
/* Initialize EH context.
! This will be called only once, since we change GET_EH_CONTEXT
pointer to another routine. */
static struct eh_context *
--- 3140,3153 ----
/* Try to create the key. If it fails, revert to static method,
otherwise start using thread specific EH contexts. */
if (__gthread_key_create (&eh_context_key, &eh_context_free) == 0)
! __get_eh_context_ptr = &eh_context_specific;
else
! __get_eh_context_ptr = &eh_context_static;
}
#endif /* no __GTHREADS */
/* Initialize EH context.
! This will be called only once, since we change __GET_EH_CONTEXT_PTR
pointer to another routine. */
static struct eh_context *
***************
*** 3152,3175 ****
#if __GTHREADS
static __gthread_once_t once = __GTHREAD_ONCE_INIT;
! /* Make sure that get_eh_context does not point to us anymore.
Some systems have dummy thread routines in their libc that
return a success (Solaris 2.6 for example). */
if (__gthread_once (&once, eh_threads_initialize) != 0
! || get_eh_context == &eh_context_initialize)
{
/* Use static version of EH context. */
! get_eh_context = &eh_context_static;
}
#else /* no __GTHREADS */
/* Use static version of EH context. */
! get_eh_context = &eh_context_static;
#endif /* no __GTHREADS */
! return (*get_eh_context) ();
}
/* Return a static EH context. */
--- 3156,3179 ----
#if __GTHREADS
static __gthread_once_t once = __GTHREAD_ONCE_INIT;
! /* Make sure that __get_eh_context_ptr does not point to us anymore.
Some systems have dummy thread routines in their libc that
return a success (Solaris 2.6 for example). */
if (__gthread_once (&once, eh_threads_initialize) != 0
! || __get_eh_context_ptr == &eh_context_initialize)
{
/* Use static version of EH context. */
! __get_eh_context_ptr = &eh_context_static;
}
#else /* no __GTHREADS */
/* Use static version of EH context. */
! __get_eh_context_ptr = &eh_context_static;
#endif /* no __GTHREADS */
! return (*__get_eh_context_ptr) ();
}
/* Return a static EH context. */
***************
*** 3179,3185 ****
{
static struct eh_context *eh;
if (! eh)
! eh = new_eh_context ();
return eh;
}
--- 3183,3189 ----
{
static struct eh_context *eh;
if (! eh)
! eh = __new_eh_context ();
return eh;
}
***************
*** 3193,3199 ****
eh = (struct eh_context *) __gthread_getspecific (eh_context_key);
if (! eh)
{
! eh = new_eh_context ();
if (__gthread_setspecific (eh_context_key, (void *) eh) != 0)
__terminate ();
}
--- 3197,3203 ----
eh = (struct eh_context *) __gthread_getspecific (eh_context_key);
if (! eh)
{
! eh = __new_eh_context ();
if (__gthread_setspecific (eh_context_key, (void *) eh) != 0)
__terminate ();
}
***************
*** 3218,3224 ****
void ***
__get_dynamic_handler_chain ()
{
! struct eh_context *eh = (*get_eh_context) ();
return &eh->dynamic_handler_chain;
}
--- 3222,3228 ----
void ***
__get_dynamic_handler_chain ()
{
! struct eh_context *eh = (*__get_eh_context_ptr) ();
return &eh->dynamic_handler_chain;
}
***************
*** 3233,3239 ****
void
__sjthrow ()
{
! struct eh_context *eh = (*get_eh_context) ();
void ***dhc = &eh->dynamic_handler_chain;
void *jmpbuf;
void (*func)(void *, int);
--- 3237,3243 ----
void
__sjthrow ()
{
! struct eh_context *eh = (*__get_eh_context_ptr) ();
void ***dhc = &eh->dynamic_handler_chain;
void *jmpbuf;
void (*func)(void *, int);
***************
*** 3309,3315 ****
void
__sjpopnthrow ()
{
! struct eh_context *eh = (*get_eh_context) ();
void ***dhc = &eh->dynamic_handler_chain;
void (*func)(void *, int);
void *arg;
--- 3313,3319 ----
void
__sjpopnthrow ()
{
! struct eh_context *eh = (*__get_eh_context_ptr) ();
void ***dhc = &eh->dynamic_handler_chain;
void (*func)(void *, int);
void *arg;
***************
*** 3597,3603 ****
void
__throw ()
{
! struct eh_context *eh = (*get_eh_context) ();
void *saved_pc, *pc, *handler, *retaddr;
frame_state ustruct, ustruct2;
frame_state *udata = &ustruct;
--- 3601,3607 ----
void
__throw ()
{
! struct eh_context *eh = (*__get_eh_context_ptr) ();
void *saved_pc, *pc, *handler, *retaddr;
frame_state ustruct, ustruct2;
frame_state *udata = &ustruct;