You've already forked linux-packaging-mono
Merge branch 'upstream'
Former-commit-id: bd9916021a63d700a72bf8bd6c46f61d072f4241
This commit is contained in:
@@ -396,7 +396,8 @@ GC_bool GC_register_main_static_data()
|
||||
|
||||
# if (defined(LINUX) || defined (__GLIBC__) || defined(NACL)) /* Are others OK here, too? */ \
|
||||
&& (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \
|
||||
|| (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG)))
|
||||
|| (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG))) \
|
||||
|| defined(OPENBSD)
|
||||
|
||||
/* We have the header files for a glibc that includes dl_iterate_phdr. */
|
||||
/* It may still not be available in the library on the target system. */
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user