static void* ms_get_empty_block (void) { char *p; int i; void *block, *empty, *next; retry: if (!empty_blocks) { p = mono_sgen_alloc_os_memory_aligned (MS_BLOCK_SIZE * MS_BLOCK_ALLOC_NUM, MS_BLOCK_SIZE, TRUE); for (i = 0; i < MS_BLOCK_ALLOC_NUM; ++i) { block = p; /* * We do the free list update one after the * other so that other threads can use the new * blocks as quickly as possible. */ do { empty = empty_blocks; *(void**)block = empty; } while (SGEN_CAS_PTR (&empty_blocks, block, empty) != empty); p += MS_BLOCK_SIZE; } SGEN_ATOMIC_ADD (num_empty_blocks, MS_BLOCK_ALLOC_NUM); stat_major_blocks_alloced += MS_BLOCK_ALLOC_NUM; } do { empty = empty_blocks; if (!empty) goto retry; block = empty; next = *(void**)block; } while (SGEN_CAS_PTR (&empty_blocks, next, empty) != empty); SGEN_ATOMIC_ADD (num_empty_blocks, -1); *(void**)block = NULL; g_assert (!((mword)block & (MS_BLOCK_SIZE - 1))); mono_sgen_update_heap_boundaries ((mword)block, (mword)block + MS_BLOCK_SIZE); return block; }
static void ms_free_block (void *block) { void *empty; memset (block, 0, MS_BLOCK_SIZE); do { empty = empty_blocks; *(void**)block = empty; } while (SGEN_CAS_PTR (&empty_blocks, block, empty) != empty); SGEN_ATOMIC_ADD (num_empty_blocks, 1); }
static void ms_free_block (void *block) { void *empty; mono_sgen_release_space (MS_BLOCK_SIZE, SPACE_MAJOR); memset (block, 0, MS_BLOCK_SIZE); do { empty = empty_blocks; *(void**)block = empty; } while (SGEN_CAS_PTR (&empty_blocks, block, empty) != empty); SGEN_ATOMIC_ADD (num_empty_blocks, 1); }
static gboolean workers_dequeue_and_do_job (WorkerData *data) { JobQueueEntry *entry; int num_finished; /* * At this point the GC might not be running anymore. We * could have been woken up by a job that was then taken by * another thread, after which the collection finished, so we * first have to successfully dequeue a job before doing * anything assuming that the collection is still ongoing. */ if (!workers_job_queue_num_entries) return FALSE; mono_mutex_lock (&workers_job_queue_mutex); entry = (JobQueueEntry*)workers_job_queue; if (entry) { workers_job_queue = entry->next; --workers_job_queue_num_entries; } mono_mutex_unlock (&workers_job_queue_mutex); if (!entry) return FALSE; g_assert (collection_needs_workers ()); entry->func (data, entry->data); sgen_free_internal (entry, INTERNAL_MEM_JOB_QUEUE_ENTRY); SGEN_ATOMIC_ADD (workers_num_jobs_finished, 1); return TRUE; }