Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/libgc
diff options
context:
space:
mode:
Diffstat (limited to 'libgc')
-rw-r--r--libgc/include/gc.h12
-rw-r--r--libgc/pthread_support.c2
-rw-r--r--libgc/win32_threads.c48
3 files changed, 59 insertions, 3 deletions
diff --git a/libgc/include/gc.h b/libgc/include/gc.h
index e7929918ad0..c9c20e65a6c 100644
--- a/libgc/include/gc.h
+++ b/libgc/include/gc.h
@@ -835,6 +835,18 @@ typedef GC_PTR (*GC_fn_type) GC_PROTO((GC_PTR client_data));
GC_API GC_PTR GC_call_with_alloc_lock
GC_PROTO((GC_fn_type fn, GC_PTR client_data));
+/*
+ * These are similar to GC_do_blocking () in upstream bdwgc. The design is
+ * simpler in that there is no distinction between active and inactive stack
+ * frames; instead, while a thread is in blocking state, it promises to not
+ * interact with the GC at all, and to not keep any pointers to GC memory
+ * around from before entering blocking state. Additionally, these can be
+ * called unbalanced (they simply set a flag internally).
+ */
+GC_API void GC_start_blocking GC_PROTO((void));
+
+GC_API void GC_end_blocking GC_PROTO((void));
+
/* The following routines are primarily intended for use with a */
/* preprocessor which inserts calls to check C pointer arithmetic. */
/* They indicate failure by invoking the corresponding _print_proc. */
diff --git a/libgc/pthread_support.c b/libgc/pthread_support.c
index 6d240f65f0e..3ff89b29222 100644
--- a/libgc/pthread_support.c
+++ b/libgc/pthread_support.c
@@ -1245,7 +1245,6 @@ void GC_start_blocking(void) {
GC_thread me;
LOCK();
me = GC_lookup_thread(pthread_self());
- GC_ASSERT(!(me -> thread_blocked));
# ifdef SPARC
me -> stop_info.stack_ptr = (ptr_t)GC_save_regs_in_stack();
# else
@@ -1273,7 +1272,6 @@ void GC_end_blocking(void) {
GC_thread me;
LOCK(); /* This will block if the world is stopped. */
me = GC_lookup_thread(pthread_self());
- GC_ASSERT(me -> thread_blocked);
me -> thread_blocked = FALSE;
UNLOCK();
}
diff --git a/libgc/win32_threads.c b/libgc/win32_threads.c
index 5533b8f2e25..425d41a9892 100644
--- a/libgc/win32_threads.c
+++ b/libgc/win32_threads.c
@@ -48,6 +48,7 @@ struct GC_thread_Rep {
/* 0 ==> entry not valid. */
/* !in_use ==> stack_base == 0 */
GC_bool suspended;
+ GC_bool thread_blocked;
# ifdef CYGWIN32
void *status; /* hold exit value until join in case it's a pointer */
@@ -174,6 +175,7 @@ static GC_thread GC_new_thread(void) {
/* the world, wait here. Hopefully this can't happen on any */
/* systems that don't allow us to block here. */
while (GC_please_stop) Sleep(20);
+ GC_ASSERT(!thread_table[i]->thread_blocked);
return thread_table + i;
}
@@ -223,7 +225,6 @@ static void GC_delete_thread(DWORD thread_id) {
}
}
-
#ifdef CYGWIN32
/* Return a GC_thread corresponding to a given pthread_t. */
@@ -245,6 +246,20 @@ static GC_thread GC_lookup_thread(pthread_t id)
return thread_table + i;
}
+#else
+
+static GC_thread GC_lookup_thread(DWORD id)
+{
+ int i;
+ LONG max = GC_get_max_thread_index();
+
+ for (i = 0; i <= max; i++)
+ if (thread_table[i].in_use && thread_table[i].id == id)
+ return &thread_table[i];
+
+ return NULL;
+}
+
#endif /* CYGWIN32 */
void GC_push_thread_structures GC_PROTO((void))
@@ -264,6 +279,35 @@ void GC_push_thread_structures GC_PROTO((void))
# endif
}
+/* Wrappers for functions that are likely to block for an appreciable */
+/* length of time. Must be called in pairs, if at all. */
+/* Nothing much beyond the system call itself should be executed */
+/* between these. */
+
+void GC_start_blocking(void) {
+ GC_thread me;
+ LOCK();
+#ifdef CYGWIN32
+ me = GC_lookup_thread(pthread_self());
+#else
+ me = GC_lookup_thread(GetCurrentThreadId());
+#endif
+ me->thread_blocked = TRUE;
+ UNLOCK();
+}
+
+void GC_end_blocking(void) {
+ GC_thread me;
+ LOCK(); /* This will block if the world is stopped. */
+#ifdef CYGWIN32
+ me = GC_lookup_thread(pthread_self());
+#else
+ me = GC_lookup_thread(GetCurrentThreadId());
+#endif
+ me->thread_blocked = FALSE;
+ UNLOCK();
+}
+
/* Defined in misc.c */
extern CRITICAL_SECTION GC_write_cs;
@@ -281,6 +325,8 @@ void GC_stop_world()
for (i = 0; i <= GC_get_max_thread_index(); i++)
if (thread_table[i].stack_base != 0
&& thread_table[i].id != thread_id) {
+ if (thread_table [i].thread_blocked)
+ continue;
# ifdef MSWINCE
/* SuspendThread will fail if thread is running kernel code */
while (SuspendThread(thread_table[i].handle) == (DWORD)-1)