diff --git a/mono/metadata/sgen-stw.c b/mono/metadata/sgen-stw.c index fc1de7c25f87..a249261673f2 100644 --- a/mono/metadata/sgen-stw.c +++ b/mono/metadata/sgen-stw.c @@ -28,6 +28,94 @@ #include "utils/mono-threads.h" #include "utils/mono-threads-debug.h" +#if defined (PLATFORM_MACOSX) + +#include +#include +#include +#include +#include + +#if defined(__x86_64__) + +#define MACH_HEADER_TYPE struct mach_header_64 +#define NLIST_TYPE struct nlist_64 +#define OFFSET_TYPE uint64_t + +#elif (defined(i386) || defined(__i386__)) + +#define MACH_HEADER_TYPE struct mach_header +#define NLIST_TYPE struct nlist +#define OFFSET_TYPE uint32_t + +#endif + +const char *OAExcludeMachThreadID_function_name = "___OAExcludeMachThreadID"; +static void (*OAExcludeMachThreadID) (pthread_t, int) = NULL; + +static OFFSET_TYPE +offset_for_symbol (struct symtab_command *symtab, uint8_t *data, const char *symbol_name) +{ + NLIST_TYPE *nlist = (NLIST_TYPE *)(data + symtab->symoff); + char *strtab = (char *) (data + symtab->stroff); + + for (int i = 0; i < symtab->nsyms; ++i, nlist++) { + const char *name = nlist->n_un.n_strx ? strtab + nlist->n_un.n_strx : NULL; + if (name != NULL && strcmp(symbol_name, name) == 0) { + OFFSET_TYPE offset = nlist->n_value; + return offset; + } + } + + return 0; +} + +static void +mono_sgen_dylib_loaded (const struct mach_header *header, intptr_t slide) +{ + Dl_info image_info; + int result = dladdr(header, &image_info); + if (result == 0) + return; + + const char *image_name = image_info.dli_fname; + if (strstr(image_name, "liboainject.dylib") == NULL) + return; + + struct load_command *cmd = (struct load_command*)((char *) header + sizeof(MACH_HEADER_TYPE)); + + for (int commandIndex = 0; commandIndex < header->ncmds; commandIndex++) { + if (cmd->cmd == LC_SYMTAB) { + OFFSET_TYPE offset = offset_for_symbol((struct symtab_command *) cmd, (uint8_t *) header, OAExcludeMachThreadID_function_name); + if (offset != 0) { + OAExcludeMachThreadID = (void (*)(pthread_t, int)) (slide + offset); + } + + return; + } + + cmd = (struct load_command *) ((char *) cmd + cmd->cmdsize); + } +} + +static void +mono_sgen_dylib_unloaded (const struct mach_header *header, intptr_t slide) +{ + Dl_info image_info; + int result = dladdr(header, &image_info); + if (result == 0) + return; + + const char *image_name = image_info.dli_fname; + if (strstr(image_name, "liboainject.dylib") == NULL) + return; + + OAExcludeMachThreadID = NULL; +} + +#endif + + #define TV_DECLARE SGEN_TV_DECLARE #define TV_GETTIME SGEN_TV_GETTIME #define TV_ELAPSED SGEN_TV_ELAPSED @@ -132,12 +220,22 @@ sgen_client_stop_world (int generation) sgen_memgov_collection_start (generation); if (sgen_need_bridge_processing ()) sgen_bridge_reset_data (); + +#if defined (PLATFORM_MACOSX) + if (OAExcludeMachThreadID != NULL) + OAExcludeMachThreadID(pthread_self(), 1); +#endif } /* LOCKING: assumes the GC lock is held */ void sgen_client_restart_world (int generation, gint64 *stw_time) { +#if defined (PLATFORM_MACOSX) + if (OAExcludeMachThreadID != NULL) + OAExcludeMachThreadID(pthread_self(), 0); +#endif + TV_DECLARE (end_sw); TV_DECLARE (start_handshake); unsigned long usec; @@ -186,6 +284,11 @@ mono_sgen_init_stw (void) { mono_counters_register ("World stop", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_stop_world); mono_counters_register ("World restart", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &time_restart_world); + +#if defined (PLATFORM_MACOSX) + _dyld_register_func_for_add_image (&mono_sgen_dylib_loaded); + _dyld_register_func_for_remove_image (&mono_sgen_dylib_unloaded); +#endif } /* Unified suspend code */