pthread_stop_world.c (GC_suspend_handler): Redirect to suspension routine if signal is received and thread is flagged...

* pthread_stop_world.c (GC_suspend_handler): Redirect to suspension
        routine if signal is received and thread is flagged SUSPENDED.
        (suspend_self): New function.
        (GC_suspend_thread): New function.
        (GC_resume_thread): New function.
        * include/gc.h (GC_suspend_thread): Declare.
        (GC_resumet_thread): Declare.
        * include/private/pthread_support.h (SUSPENDED): New GC_thread
        flag.

From-SVN: r114869
This commit is contained in:
Keith Seitz 2006-06-21 20:56:37 +00:00 committed by Keith Seitz
parent c3238e32eb
commit 7691d0d3c9
4 changed files with 82 additions and 6 deletions

View File

@ -1,3 +1,15 @@
2006-06-21 Keith Seitz <keiths@redhat.com>
* pthread_stop_world.c (GC_suspend_handler): Redirect to suspension
routine if signal is received and thread is flagged SUSPENDED.
(suspend_self): New function.
(GC_suspend_thread): New function.
(GC_resume_thread): New function.
* include/gc.h (GC_suspend_thread): Declare.
(GC_resumet_thread): Declare.
* include/private/pthread_support.h (SUSPENDED): New GC_thread
flag.
2006-06-20 Ranjit Mathew <rmathew@gcc.gnu.org>
Backport Windows 9x/ME VirtualQuery() fix from GC 6.7.

View File

@ -1040,4 +1040,14 @@ GC_API void GC_register_has_static_roots_callback
} /* end of extern "C" */
#endif
/* External thread suspension support. These functions do not implement
* suspension counts or any other higher-level abstraction. Threads which
* have been suspended numerous times will resume with the very first call
* to GC_resume_thread.
*/
#if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
&& !defined(GC_WIN32_THREADS) && !defined(GC_DARWIN_THREADS)
GC_API void GC_suspend_thread GC_PROTO((pthread_t));
GC_API void GC_resume_thread GC_PROTO((pthread_t));
#endif
#endif /* _GC_H */

View File

@ -33,6 +33,7 @@ typedef struct GC_Thread_Rep {
# define FINISHED 1 /* Thread has exited. */
# define DETACHED 2 /* Thread is intended to be detached. */
# define MAIN_THREAD 4 /* True for the original thread only. */
# define SUSPENDED 8 /* True if thread was suspended externally */
short thread_blocked; /* Protected by GC lock. */
/* Treated as a boolean value. If set, */
/* thread will acquire GC lock before */

View File

@ -13,6 +13,8 @@
/* Doesn't exist on HP/UX 11.11. */
#endif
void suspend_self();
#if DEBUG_THREADS
#ifndef NSIG
@ -127,9 +129,14 @@ extern void GC_with_callee_saves_pushed();
void GC_suspend_handler(int sig)
{
int old_errno = errno;
GC_with_callee_saves_pushed(GC_suspend_handler_inner, (ptr_t)(word)sig);
errno = old_errno;
GC_thread me = GC_lookup_thread (pthread_self());
if (me -> flags & SUSPENDED)
suspend_self();
else {
int old_errno = errno;
GC_with_callee_saves_pushed(GC_suspend_handler_inner, (ptr_t)(word)sig);
errno = old_errno;
}
}
#else
@ -137,9 +144,14 @@ void GC_suspend_handler(int sig)
/* in the signal handler frame. */
void GC_suspend_handler(int sig)
{
int old_errno = errno;
GC_suspend_handler_inner((ptr_t)(word)sig);
errno = old_errno;
GC_thread me = GC_lookup_thread(pthread_self());
if (me -> flags & SUSPENDED)
suspend_self();
else {
int old_errno = errno;
GC_suspend_handler_inner((ptr_t)(word)sig);
errno = old_errno;
}
}
#endif
@ -430,6 +442,47 @@ void GC_stop_world()
GC_stopping_thread = 0; /* debugging only */
}
void suspend_self() {
GC_thread me = GC_lookup_thread(pthread_self());
if (me == NULL)
ABORT("attempting to suspend unknown thread");
me -> flags |= SUSPENDED;
GC_start_blocking();
while (me -> flags & SUSPENDED)
GC_brief_async_signal_safe_sleep();
GC_end_blocking();
}
void GC_suspend_thread(pthread_t thread) {
if (thread == pthread_self())
suspend_self();
else {
int result;
GC_thread t = GC_lookup_thread(thread);
if (t == NULL)
ABORT("attempting to suspend unknown thread");
t -> flags |= SUSPENDED;
result = pthread_kill (t -> id, SIG_SUSPEND);
switch (result) {
case ESRCH:
case 0:
break;
default:
ABORT("pthread_kill failed");
}
}
}
void GC_resume_thread(pthread_t thread) {
GC_thread t = GC_lookup_thread(thread);
if (t == NULL)
ABORT("attempting to resume unknown thread");
t -> flags &= ~SUSPENDED;
}
/* Caller holds allocation lock, and has held it continuously since */
/* the world stopped. */
void GC_start_world()