static gboolean ms_alloc_block (int size_index, gboolean pinned, gboolean has_references) { int size = block_obj_sizes [size_index]; int count = MS_BLOCK_FREE / size; MSBlockInfo *info; #ifndef FIXED_HEAP MSBlockHeader *header; #endif MSBlockInfo **free_blocks = FREE_BLOCKS (pinned, has_references); char *obj_start; int i; if (!mono_sgen_try_alloc_space (MS_BLOCK_SIZE, SPACE_MAJOR)) return FALSE; #ifdef FIXED_HEAP info = ms_get_empty_block (); #else info = mono_sgen_alloc_internal (INTERNAL_MEM_MS_BLOCK_INFO); #endif DEBUG (9, g_assert (count >= 2)); info->obj_size = size; info->obj_size_index = size_index; info->pinned = pinned; info->has_references = has_references; info->has_pinned = pinned; info->is_to_space = (mono_sgen_get_current_collection_generation () == GENERATION_OLD); #ifndef FIXED_HEAP info->block = ms_get_empty_block (); header = (MSBlockHeader*) info->block; header->info = info; #endif update_heap_boundaries_for_block (info); /* build free list */ obj_start = info->block + MS_BLOCK_SKIP; info->free_list = (void**)obj_start; /* we're skipping the last one - it must be nulled */ for (i = 0; i < count - 1; ++i) { char *next_obj_start = obj_start + size; *(void**)obj_start = next_obj_start; obj_start = next_obj_start; } /* the last one */ *(void**)obj_start = NULL; info->next_free = free_blocks [size_index]; free_blocks [size_index] = info; info->next = all_blocks; all_blocks = info; ++num_major_sections; return TRUE; }
static void add_generic_store_remset_from_buffer (gpointer *buffer) { GenericStoreRememberedSet *remset = mono_sgen_alloc_internal (INTERNAL_MEM_STORE_REMSET); memcpy (remset->data, buffer + 1, sizeof (gpointer) * (STORE_REMSET_BUFFER_SIZE - 1)); remset->next = generic_store_remsets; generic_store_remsets = remset; }
/*MUST be called with world stopped*/ static Fragment* alloc_fragment (void) { Fragment *frag = fragment_freelist; if (frag) { fragment_freelist = frag->next_free; frag->next_free = NULL; return frag; } frag = mono_sgen_alloc_internal (INTERNAL_MEM_FRAGMENT); frag->next_free = NULL; return frag; }
static void ms_alloc_block (int size_index, gboolean pinned, gboolean has_references) { int size = block_obj_sizes [size_index]; int count = MS_BLOCK_FREE / size; #ifdef FIXED_HEAP MSBlockInfo *info = ms_get_empty_block (); #else MSBlockInfo *info = mono_sgen_alloc_internal (INTERNAL_MEM_MS_BLOCK_INFO); MSBlockHeader *header; #endif MSBlockInfo **free_blocks = FREE_BLOCKS (pinned, has_references); char *obj_start; int i; DEBUG (9, g_assert (count >= 2)); info->obj_size = size; info->pinned = pinned; info->has_references = has_references; #ifndef FIXED_HEAP info->block = ms_get_empty_block (); header = (MSBlockHeader*) info->block; header->info = info; #endif /* build free list */ obj_start = info->block + MS_BLOCK_SKIP; info->free_list = (void**)obj_start; /* we're skipping the last one - it must be nulled */ for (i = 0; i < count - 1; ++i) { char *next_obj_start = obj_start + size; *(void**)obj_start = next_obj_start; obj_start = next_obj_start; } /* the last one */ *(void**)obj_start = NULL; info->next_free = free_blocks [size_index]; free_blocks [size_index] = info; #ifndef FIXED_HEAP info->next = all_blocks; all_blocks = info; #endif ++num_major_sections; }
static void mono_sgen_ssb_register_thread (SgenThreadInfo *info) { #ifndef HAVE_KW_THREAD SgenThreadInfo *__thread_info__ = info; #endif info->remset = mono_sgen_alloc_remset (DEFAULT_REMSET_SIZE, info, FALSE); mono_native_tls_set_value (remembered_set_key, info->remset); #ifdef HAVE_KW_THREAD remembered_set = info->remset; #endif STORE_REMSET_BUFFER = mono_sgen_alloc_internal (INTERNAL_MEM_STORE_REMSET); STORE_REMSET_BUFFER_INDEX = 0; }
/* LOCKING: assumes the GC lock is held */ static void add_or_remove_disappearing_link (MonoObject *obj, void **link, int generation) { DisappearingLinkHashTable *hash_table = get_dislink_hash_table (generation); DisappearingLink *entry, *prev; unsigned int hash; DisappearingLink **disappearing_link_hash = hash_table->table; int disappearing_link_hash_size = hash_table->size; if (hash_table->num_links >= disappearing_link_hash_size * 2) { rehash_dislink (hash_table); disappearing_link_hash = hash_table->table; disappearing_link_hash_size = hash_table->size; } /* FIXME: add check that link is not in the heap */ hash = mono_aligned_addr_hash (link) % disappearing_link_hash_size; entry = disappearing_link_hash [hash]; prev = NULL; for (; entry; entry = entry->next) { /* link already added */ if (link == entry->link) { /* NULL obj means remove */ if (obj == NULL) { if (prev) prev->next = entry->next; else disappearing_link_hash [hash] = entry->next; hash_table->num_links--; DEBUG (5, fprintf (gc_debug_file, "Removed dislink %p (%d) from %s table\n", entry, hash_table->num_links, generation_name (generation))); mono_sgen_free_internal (entry, INTERNAL_MEM_DISLINK); } return; } prev = entry; } if (obj == NULL) return; entry = mono_sgen_alloc_internal (INTERNAL_MEM_DISLINK); entry->link = link; entry->next = disappearing_link_hash [hash]; disappearing_link_hash [hash] = entry; hash_table->num_links++; DEBUG (5, fprintf (gc_debug_file, "Added dislink %p for object: %p (%s) at %p to %s table\n", entry, obj, obj->vtable->klass->name, link, generation_name (generation))); }
/* LOCKING: requires that the GC lock is held */ static void register_for_finalization (MonoObject *obj, void *user_data, int generation) { FinalizeEntryHashTable *hash_table = get_finalize_entry_hash_table (generation); FinalizeEntry **finalizable_hash; mword finalizable_hash_size; FinalizeEntry *entry, *prev; unsigned int hash; if (no_finalize) return; g_assert (user_data == NULL || user_data == mono_gc_run_finalize); hash = mono_object_hash (obj); rehash_fin_table_if_necessary (hash_table); finalizable_hash = hash_table->table; finalizable_hash_size = hash_table->size; hash %= finalizable_hash_size; prev = NULL; for (entry = finalizable_hash [hash]; entry; entry = entry->next) { if (entry->object == obj) { if (!user_data) { /* remove from the list */ if (prev) prev->next = entry->next; else finalizable_hash [hash] = entry->next; hash_table->num_registered--; DEBUG (5, fprintf (gc_debug_file, "Removed finalizer %p for object: %p (%s) (%d)\n", entry, obj, obj->vtable->klass->name, hash_table->num_registered)); mono_sgen_free_internal (entry, INTERNAL_MEM_FINALIZE_ENTRY); } return; } prev = entry; } if (!user_data) { /* request to deregister, but already out of the list */ return; } entry = mono_sgen_alloc_internal (INTERNAL_MEM_FINALIZE_ENTRY); entry->object = obj; entry->next = finalizable_hash [hash]; finalizable_hash [hash] = entry; hash_table->num_registered++; DEBUG (5, fprintf (gc_debug_file, "Added finalizer %p for object: %p (%s) (%d) to %s table\n", entry, obj, obj->vtable->klass->name, hash_table->num_registered, generation_name (generation))); }
static void gray_object_alloc_queue_section (GrayQueue *queue) { GrayQueueSection *section; if (queue->free_list) { /* Use the previously allocated queue sections if possible */ section = queue->free_list; queue->free_list = section->next; } else { /* Allocate a new section */ section = mono_sgen_alloc_internal (INTERNAL_MEM_GRAY_QUEUE); } section->end = 0; /* Link it with the others */ section->next = queue->first; queue->first = section; }
static void workers_enqueue_job (JobFunc func, void *data) { int num_entries; JobQueueEntry *entry; if (!collection_is_parallel ()) { func (NULL, data); return; } entry = mono_sgen_alloc_internal (INTERNAL_MEM_JOB_QUEUE_ENTRY); entry->func = func; entry->data = data; pthread_mutex_lock (&workers_job_queue_mutex); entry->next = workers_job_queue; workers_job_queue = entry; num_entries = ++workers_job_queue_num_entries; pthread_mutex_unlock (&workers_job_queue_mutex); workers_wake_up (num_entries); }