X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fsgen-protocol.c;h=f827beb8a866edde4a6b526b0b522e5712f33f37;hb=66311912de21f9cd0f7c4740ea9af519f420a393;hp=c41df40339f927a4f140231ec7317e9f020a468c;hpb=90d6059c5475419ddf6e0fc4b49098158010cab0;p=mono.git diff --git a/mono/metadata/sgen-protocol.c b/mono/metadata/sgen-protocol.c index c41df40339f..f827beb8a86 100644 --- a/mono/metadata/sgen-protocol.c +++ b/mono/metadata/sgen-protocol.c @@ -29,10 +29,15 @@ #include "utils/mono-mmap.h" #include "utils/mono-threads.h" -#ifdef SGEN_BINARY_PROTOCOL +#include +#ifdef HAVE_UNISTD_H +#include +#endif -/* If not null, dump binary protocol to this file */ -static FILE *binary_protocol_file = NULL; +/* FIXME Implement binary protocol IO on systems that don't have unistd */ +#ifdef HAVE_UNISTD_H +/* If valid, dump binary protocol to this file */ +static int binary_protocol_file = -1; /* We set this to -1 to indicate an exclusive lock */ static volatile int binary_protocol_use_count = 0; @@ -48,16 +53,84 @@ struct _BinaryProtocolBuffer { static BinaryProtocolBuffer * volatile binary_protocol_buffers = NULL; +static char* filename_or_prefix = NULL; +static int current_file_index = 0; +static long long current_file_size = 0; +static long long file_size_limit; + +static char* +filename_for_index (int index) +{ + char *filename; + + SGEN_ASSERT (0, file_size_limit > 0, "Indexed binary protocol filename must only be used with file size limit"); + + filename = sgen_alloc_internal_dynamic (strlen (filename_or_prefix) + 32, INTERNAL_MEM_BINARY_PROTOCOL, TRUE); + sprintf (filename, "%s.%d", filename_or_prefix, index); + + return filename; +} + +static void +free_filename (char *filename) +{ + SGEN_ASSERT (0, file_size_limit > 0, "Indexed binary protocol filename must only be used with file size limit"); + + sgen_free_internal_dynamic (filename, strlen (filename_or_prefix) + 32, INTERNAL_MEM_BINARY_PROTOCOL); +} + +static void +binary_protocol_open_file (void) +{ + char *filename; + + if (file_size_limit > 0) + filename = filename_for_index (current_file_index); + else + filename = filename_or_prefix; + + do { + binary_protocol_file = open (filename, O_CREAT|O_WRONLY|O_TRUNC, 0644); + if (binary_protocol_file == -1 && errno != EINTR) + break; /* Failed */ + } while (binary_protocol_file == -1); + + if (file_size_limit > 0) + free_filename (filename); +} +#endif + void -binary_protocol_init (const char *filename) +binary_protocol_init (const char *filename, long long limit) { - binary_protocol_file = fopen (filename, "w"); +#ifdef HAVE_UNISTD_H + filename_or_prefix = sgen_alloc_internal_dynamic (strlen (filename) + 1, INTERNAL_MEM_BINARY_PROTOCOL, TRUE); + strcpy (filename_or_prefix, filename); + + file_size_limit = limit; + + binary_protocol_open_file (); +#endif } gboolean binary_protocol_is_enabled (void) { - return binary_protocol_file != NULL; +#ifdef HAVE_UNISTD_H + return binary_protocol_file != -1; +#else + return FALSE; +#endif +} + +#ifdef HAVE_UNISTD_H + +static void +close_binary_protocol_file (void) +{ + while (close (binary_protocol_file) == -1 && errno == EINTR) + ; + binary_protocol_file = -1; } static gboolean @@ -110,20 +183,56 @@ unlock_recursive (void) static void binary_protocol_flush_buffer (BinaryProtocolBuffer *buffer) { + ssize_t ret; + size_t to_write = buffer->index; + size_t written = 0; g_assert (buffer->index > 0); - fwrite (buffer->buffer, 1, buffer->index, binary_protocol_file); + + while (written < to_write) { + ret = write (binary_protocol_file, buffer->buffer + written, to_write - written); + if (ret >= 0) + written += ret; + else if (errno == EINTR) + continue; + else + close_binary_protocol_file (); + } + + current_file_size += buffer->index; sgen_free_os_memory (buffer, sizeof (BinaryProtocolBuffer), SGEN_ALLOC_INTERNAL); } +static void +binary_protocol_check_file_overflow (void) +{ + if (file_size_limit <= 0 || current_file_size < file_size_limit) + return; + + close_binary_protocol_file (); + + if (current_file_index > 0) { + char *filename = filename_for_index (current_file_index - 1); + unlink (filename); + free_filename (filename); + } + + ++current_file_index; + current_file_size = 0; + + binary_protocol_open_file (); +} +#endif + void binary_protocol_flush_buffers (gboolean force) { +#ifdef HAVE_UNISTD_H int num_buffers = 0, i; BinaryProtocolBuffer *buf; BinaryProtocolBuffer **bufs; - if (!binary_protocol_file) + if (binary_protocol_file == -1) return; if (!force && !try_lock_exclusive ()) @@ -138,22 +247,23 @@ binary_protocol_flush_buffers (gboolean force) binary_protocol_buffers = NULL; - for (i = num_buffers - 1; i >= 0; --i) + for (i = num_buffers - 1; i >= 0; --i) { binary_protocol_flush_buffer (bufs [i]); + binary_protocol_check_file_overflow (); + } sgen_free_internal_dynamic (buf, num_buffers * sizeof (BinaryProtocolBuffer*), INTERNAL_MEM_BINARY_PROTOCOL); if (!force) unlock_exclusive (); - - fflush (binary_protocol_file); +#endif } +#ifdef HAVE_UNISTD_H static BinaryProtocolBuffer* binary_protocol_get_buffer (int length) { BinaryProtocolBuffer *buffer, *new_buffer; - retry: buffer = binary_protocol_buffers; if (buffer && buffer->index + length <= BINARY_PROTOCOL_BUFFER_SIZE) @@ -170,15 +280,16 @@ binary_protocol_get_buffer (int length) return new_buffer; } - +#endif static void protocol_entry (unsigned char type, gpointer data, int size) { +#ifdef HAVE_UNISTD_H int index; BinaryProtocolBuffer *buffer; - if (!binary_protocol_file) + if (binary_protocol_file == -1) return; if (sgen_is_worker_thread (mono_native_thread_id_get ())) @@ -206,6 +317,7 @@ protocol_entry (unsigned char type, gpointer data, int size) g_assert (index <= BINARY_PROTOCOL_BUFFER_SIZE); unlock_recursive (); +#endif } void @@ -219,19 +331,127 @@ binary_protocol_collection_force (int generation) void binary_protocol_collection_begin (int index, int generation) { - SGenProtocolCollection entry = { index, generation }; + SGenProtocolCollectionBegin entry = { index, generation }; binary_protocol_flush_buffers (FALSE); - protocol_entry (SGEN_PROTOCOL_COLLECTION_BEGIN, &entry, sizeof (SGenProtocolCollection)); + protocol_entry (SGEN_PROTOCOL_COLLECTION_BEGIN, &entry, sizeof (SGenProtocolCollectionBegin)); } void -binary_protocol_collection_end (int index, int generation) +binary_protocol_collection_end (int index, int generation, long long num_objects_scanned, long long num_unique_objects_scanned) { - SGenProtocolCollection entry = { index, generation }; + SGenProtocolCollectionEnd entry = { index, generation, num_objects_scanned, num_unique_objects_scanned }; binary_protocol_flush_buffers (FALSE); - protocol_entry (SGEN_PROTOCOL_COLLECTION_END, &entry, sizeof (SGenProtocolCollection)); + protocol_entry (SGEN_PROTOCOL_COLLECTION_END, &entry, sizeof (SGenProtocolCollectionEnd)); } +void +binary_protocol_concurrent_start (void) +{ + protocol_entry (SGEN_PROTOCOL_CONCURRENT_START, NULL, 0); +} + +void +binary_protocol_concurrent_update_finish (void) +{ + protocol_entry (SGEN_PROTOCOL_CONCURRENT_UPDATE_FINISH, NULL, 0); +} + +void +binary_protocol_world_stopping (long long timestamp) +{ + SGenProtocolWorldStopping entry = { timestamp }; + protocol_entry (SGEN_PROTOCOL_WORLD_STOPPING, &entry, sizeof (SGenProtocolWorldStopping)); +} + +void +binary_protocol_world_stopped (long long timestamp, long long total_major_cards, + long long marked_major_cards, long long total_los_cards, long long marked_los_cards) +{ + SGenProtocolWorldStopped entry = { timestamp, total_major_cards, marked_major_cards, total_los_cards, marked_los_cards }; + protocol_entry (SGEN_PROTOCOL_WORLD_STOPPED, &entry, sizeof (SGenProtocolWorldStopped)); +} + +void +binary_protocol_world_restarting (int generation, long long timestamp, + long long total_major_cards, long long marked_major_cards, long long total_los_cards, long long marked_los_cards) +{ + SGenProtocolWorldRestarting entry = { generation, timestamp, total_major_cards, marked_major_cards, total_los_cards, marked_los_cards }; + protocol_entry (SGEN_PROTOCOL_WORLD_RESTARTING, &entry, sizeof (SGenProtocolWorldRestarting)); +} + +void +binary_protocol_world_restarted (int generation, long long timestamp) +{ + SGenProtocolWorldRestarted entry = { generation, timestamp }; + protocol_entry (SGEN_PROTOCOL_WORLD_RESTARTED, &entry, sizeof (SGenProtocolWorldRestarted)); +} + +void +binary_protocol_thread_suspend (gpointer thread, gpointer stopped_ip) +{ + SGenProtocolThreadSuspend entry = { thread, stopped_ip }; + protocol_entry (SGEN_PROTOCOL_THREAD_SUSPEND, &entry, sizeof (SGenProtocolThreadSuspend)); +} + +void +binary_protocol_thread_restart (gpointer thread) +{ + SGenProtocolThreadRestart entry = { thread }; + protocol_entry (SGEN_PROTOCOL_THREAD_RESTART, &entry, sizeof (SGenProtocolThreadRestart)); +} + +void +binary_protocol_thread_register (gpointer thread) +{ + SGenProtocolThreadRegister entry = { thread }; + protocol_entry (SGEN_PROTOCOL_THREAD_REGISTER, &entry, sizeof (SGenProtocolThreadRegister)); + +} + +void +binary_protocol_thread_unregister (gpointer thread) +{ + SGenProtocolThreadUnregister entry = { thread }; + protocol_entry (SGEN_PROTOCOL_THREAD_UNREGISTER, &entry, sizeof (SGenProtocolThreadUnregister)); + +} + +void +binary_protocol_missing_remset (gpointer obj, gpointer obj_vtable, int offset, gpointer value, gpointer value_vtable, int value_pinned) +{ + SGenProtocolMissingRemset entry = { obj, obj_vtable, offset, value, value_vtable, value_pinned }; + protocol_entry (SGEN_PROTOCOL_MISSING_REMSET, &entry, sizeof (SGenProtocolMissingRemset)); + +} + +void +binary_protocol_cement (gpointer obj, gpointer vtable, int size) +{ + SGenProtocolCement entry = { obj, vtable, size }; + protocol_entry (SGEN_PROTOCOL_CEMENT, &entry, sizeof (SGenProtocolCement)); +} + +void +binary_protocol_cement_reset (void) +{ + protocol_entry (SGEN_PROTOCOL_CEMENT_RESET, NULL, 0); +} + +void +binary_protocol_domain_unload_begin (gpointer domain) +{ + SGenProtocolDomainUnload entry = { domain }; + protocol_entry (SGEN_PROTOCOL_DOMAIN_UNLOAD_BEGIN, &entry, sizeof (SGenProtocolDomainUnload)); +} + +void +binary_protocol_domain_unload_end (gpointer domain) +{ + SGenProtocolDomainUnload entry = { domain }; + protocol_entry (SGEN_PROTOCOL_DOMAIN_UNLOAD_END, &entry, sizeof (SGenProtocolDomainUnload)); +} + +#ifdef SGEN_HEAVY_BINARY_PROTOCOL void binary_protocol_alloc (gpointer obj, gpointer vtable, int size) { @@ -260,6 +480,13 @@ binary_protocol_copy (gpointer from, gpointer to, gpointer vtable, int size) protocol_entry (SGEN_PROTOCOL_COPY, &entry, sizeof (SGenProtocolCopy)); } +void +binary_protocol_pin_stage (gpointer addr_ptr, gpointer addr) +{ + SGenProtocolPinStage entry = { addr_ptr, addr }; + protocol_entry (SGEN_PROTOCOL_PIN_STAGE, &entry, sizeof (SGenProtocolPinStage)); +} + void binary_protocol_pin (gpointer obj, gpointer vtable, int size) { @@ -288,6 +515,13 @@ binary_protocol_scan_vtype_begin (gpointer obj, int size) protocol_entry (SGEN_PROTOCOL_SCAN_VTYPE_BEGIN, &entry, sizeof (SGenProtocolScanVTypeBegin)); } +void +binary_protocol_scan_process_reference (gpointer obj, gpointer ptr, gpointer value) +{ + SGenProtocolScanProcessReference entry = { obj, ptr, value }; + protocol_entry (SGEN_PROTOCOL_SCAN_PROCESS_REFERENCE, &entry, sizeof (SGenProtocolScanProcessReference)); +} + void binary_protocol_wbarrier (gpointer ptr, gpointer value, gpointer value_vtable) { @@ -323,44 +557,6 @@ binary_protocol_empty (gpointer start, int size) protocol_entry (SGEN_PROTOCOL_EMPTY, &entry, sizeof (SGenProtocolEmpty)); } -void -binary_protocol_thread_suspend (gpointer thread, gpointer stopped_ip) -{ - SGenProtocolThreadSuspend entry = { thread, stopped_ip }; - protocol_entry (SGEN_PROTOCOL_THREAD_SUSPEND, &entry, sizeof (SGenProtocolThreadSuspend)); -} - -void -binary_protocol_thread_restart (gpointer thread) -{ - SGenProtocolThreadRestart entry = { thread }; - protocol_entry (SGEN_PROTOCOL_THREAD_RESTART, &entry, sizeof (SGenProtocolThreadRestart)); -} - -void -binary_protocol_thread_register (gpointer thread) -{ - SGenProtocolThreadRegister entry = { thread }; - protocol_entry (SGEN_PROTOCOL_THREAD_REGISTER, &entry, sizeof (SGenProtocolThreadRegister)); - -} - -void -binary_protocol_thread_unregister (gpointer thread) -{ - SGenProtocolThreadUnregister entry = { thread }; - protocol_entry (SGEN_PROTOCOL_THREAD_UNREGISTER, &entry, sizeof (SGenProtocolThreadUnregister)); - -} - -void -binary_protocol_missing_remset (gpointer obj, gpointer obj_vtable, int offset, gpointer value, gpointer value_vtable, int value_pinned) -{ - SGenProtocolMissingRemset entry = { obj, obj_vtable, offset, value, value_vtable, value_pinned }; - protocol_entry (SGEN_PROTOCOL_MISSING_REMSET, &entry, sizeof (SGenProtocolMissingRemset)); - -} - void binary_protocol_card_scan (gpointer start, int size) { @@ -368,19 +564,6 @@ binary_protocol_card_scan (gpointer start, int size) protocol_entry (SGEN_PROTOCOL_CARD_SCAN, &entry, sizeof (SGenProtocolCardScan)); } -void -binary_protocol_cement (gpointer obj, gpointer vtable, int size) -{ - SGenProtocolCement entry = { obj, vtable, size }; - protocol_entry (SGEN_PROTOCOL_CEMENT, &entry, sizeof (SGenProtocolCement)); -} - -void -binary_protocol_cement_reset (void) -{ - protocol_entry (SGEN_PROTOCOL_CEMENT_RESET, NULL, 0); -} - void binary_protocol_dislink_update (gpointer link, gpointer obj, int track, int staged) { @@ -403,19 +586,18 @@ binary_protocol_dislink_process_staged (gpointer link, gpointer obj, int index) } void -binary_protocol_domain_unload_begin (gpointer domain) +binary_protocol_gray_enqueue (gpointer queue, gpointer cursor, gpointer value) { - SGenProtocolDomainUnload entry = { domain }; - protocol_entry (SGEN_PROTOCOL_DOMAIN_UNLOAD_BEGIN, &entry, sizeof (SGenProtocolDomainUnload)); + SGenProtocolGrayQueue entry = { queue, cursor, value }; + protocol_entry (SGEN_PROTOCOL_GRAY_ENQUEUE, &entry, sizeof (SGenProtocolGrayQueue)); } void -binary_protocol_domain_unload_end (gpointer domain) +binary_protocol_gray_dequeue (gpointer queue, gpointer cursor, gpointer value) { - SGenProtocolDomainUnload entry = { domain }; - protocol_entry (SGEN_PROTOCOL_DOMAIN_UNLOAD_END, &entry, sizeof (SGenProtocolDomainUnload)); + SGenProtocolGrayQueue entry = { queue, cursor, value }; + protocol_entry (SGEN_PROTOCOL_GRAY_DEQUEUE, &entry, sizeof (SGenProtocolGrayQueue)); } - #endif #endif /* HAVE_SGEN_GC */