blob: 01863146c5d3ae47929d61632fb07c9e2cda4f26 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Xiao-Feng Li, 2006/10/05
*/
#include "mutator.h"
#include "../trace_forward/fspace.h"
#include "../mark_sweep/gc_ms.h"
#include "../mark_sweep/wspace.h"
#include "../finalizer_weakref/finalizer_weakref.h"
struct GC_Gen;
Space* gc_get_nos(GC_Gen* gc);
void mutator_initialize(GC* gc, void *unused_gc_information)
{
/* FIXME:: make sure gc_info is cleared */
Mutator *mutator = (Mutator *)STD_MALLOC(sizeof(Mutator));
memset(mutator, 0, sizeof(Mutator));
mutator->alloc_space = gc_get_nos((GC_Gen*)gc);
mutator->gc = gc;
if(gc_is_gen_mode()){
mutator->rem_set = free_set_pool_get_entry(gc->metadata);
assert(vector_block_is_empty(mutator->rem_set));
}
mutator->dirty_set = free_set_pool_get_entry(gc->metadata);
if(!IGNORE_FINREF )
mutator->obj_with_fin = finref_get_free_block(gc);
else
mutator->obj_with_fin = NULL;
#ifdef USE_UNIQUE_MARK_SWEEP_GC
allocator_init_local_chunks((Allocator*)mutator);
#endif
lock(gc->mutator_list_lock); // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
mutator->next = (Mutator *)gc->mutator_list;
gc->mutator_list = mutator;
gc->num_mutators++;
/*Begin to measure the mutator thread execution time. */
mutator->time_measurement_start = time_now();
unlock(gc->mutator_list_lock); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
gc_set_tls(mutator);
return;
}
void mutator_register_new_obj_size(Mutator * mutator);
void mutator_destruct(GC* gc, void *unused_gc_information)
{
Mutator *mutator = (Mutator *)gc_get_tls();
alloc_context_reset((Allocator*)mutator);
lock(gc->mutator_list_lock); // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
#ifdef USE_UNIQUE_MARK_SWEEP_GC
allocactor_destruct_local_chunks((Allocator*)mutator);
#endif
mutator_register_new_obj_size(mutator);
volatile Mutator *temp = gc->mutator_list;
if (temp == mutator) { /* it is at the head of the list */
gc->mutator_list = temp->next;
} else {
while (temp->next != mutator) {
temp = temp->next;
assert(temp);
}
temp->next = mutator->next;
}
gc->num_mutators--;
unlock(gc->mutator_list_lock); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if(gc_is_gen_mode()){ /* put back the remset when a mutator exits */
pool_put_entry(gc->metadata->mutator_remset_pool, mutator->rem_set);
mutator->rem_set = NULL;
}
if(mutator->obj_with_fin){
pool_put_entry(gc->finref_metadata->obj_with_fin_pool, mutator->obj_with_fin);
mutator->obj_with_fin = NULL;
}
lock(mutator->dirty_set_lock);
if( mutator->dirty_set != NULL){
if(vector_block_is_empty(mutator->dirty_set))
pool_put_entry(gc->metadata->free_set_pool, mutator->dirty_set);
else{ /* FIXME:: this condition may be released. */
pool_put_entry(gc->metadata->gc_dirty_set_pool, mutator->dirty_set);
mutator->dirty_set = NULL;
}
}
unlock(mutator->dirty_set_lock);
STD_FREE(mutator);
gc_set_tls(NULL);
return;
}
void gc_reset_mutator_context(GC* gc)
{
TRACE2("gc.process", "GC: reset mutator context ...\n");
Mutator *mutator = gc->mutator_list;
while (mutator) {
alloc_context_reset((Allocator*)mutator);
mutator = mutator->next;
}
return;
}
void gc_prepare_mutator_remset(GC* gc)
{
Mutator *mutator = gc->mutator_list;
while (mutator) {
mutator->rem_set = free_set_pool_get_entry(gc->metadata);
mutator = mutator->next;
}
return;
}
Boolean gc_local_dirtyset_is_empty(GC* gc)
{
lock(gc->mutator_list_lock);
Mutator *mutator = gc->mutator_list;
while (mutator) {
Vector_Block* local_dirty_set = mutator->dirty_set;
if(!vector_block_is_empty(local_dirty_set)){
unlock(gc->mutator_list_lock);
return FALSE;
}
mutator = mutator->next;
}
unlock(gc->mutator_list_lock);
return TRUE;
}
Vector_Block* gc_get_local_dirty_set(GC* gc, unsigned int shared_id)
{
lock(gc->mutator_list_lock);
Mutator *mutator = gc->mutator_list;
while (mutator) {
Vector_Block* local_dirty_set = mutator->dirty_set;
if(!vector_block_is_empty(local_dirty_set) && vector_block_set_shared(local_dirty_set,shared_id)){
unlock(gc->mutator_list_lock);
return local_dirty_set;
}
mutator = mutator->next;
}
unlock(gc->mutator_list_lock);
return NULL;
}
void gc_start_mutator_time_measure(GC* gc)
{
lock(gc->mutator_list_lock);
Mutator* mutator = gc->mutator_list;
while (mutator) {
mutator->time_measurement_start = time_now();
mutator = mutator->next;
}
unlock(gc->mutator_list_lock);
}
int64 gc_get_mutator_time(GC* gc)
{
int64 time_mutator = 0;
lock(gc->mutator_list_lock);
Mutator* mutator = gc->mutator_list;
while (mutator) {
#ifdef _DEBUG
mutator->time_measurement_end = time_now();
#endif
int64 time_measured = time_now() - mutator->time_measurement_start;
if(time_measured > time_mutator){
time_mutator = time_measured;
}
mutator = mutator->next;
}
unlock(gc->mutator_list_lock);
return time_mutator;
}
static POINTER_SIZE_INT desturcted_mutator_alloced_size;
static POINTER_SIZE_INT desturcted_mutator_alloced_num;
static POINTER_SIZE_INT desturcted_mutator_alloced_occupied_size;
static POINTER_SIZE_INT desturcted_mutator_write_barrier_marked_size;
void mutator_register_new_obj_size(Mutator * mutator)
{
desturcted_mutator_alloced_size += mutator->new_obj_size;
desturcted_mutator_alloced_num += mutator->new_obj_num;
desturcted_mutator_alloced_occupied_size += mutator->new_obj_occupied_size;
desturcted_mutator_write_barrier_marked_size += mutator->write_barrier_marked_size;
}
unsigned int gc_get_mutator_write_barrier_marked_size(GC* gc)
{
POINTER_SIZE_INT write_barrier_marked_size = 0;
lock(gc->mutator_list_lock);
Mutator* mutator = gc->mutator_list;
while (mutator) {
write_barrier_marked_size += mutator->write_barrier_marked_size;
mutator = mutator->next;
}
unlock(gc->mutator_list_lock);
return write_barrier_marked_size;
}
unsigned int gc_get_mutator_dirty_obj_num(GC *gc)
{
POINTER_SIZE_INT dirty_obj_num = 0;
lock(gc->mutator_list_lock);
Mutator* mutator = gc->mutator_list;
while (mutator) {
dirty_obj_num += mutator->dirty_obj_num;
mutator = mutator->next;
}
unlock(gc->mutator_list_lock);
return dirty_obj_num;
}
unsigned int gc_get_mutator_new_obj_size(GC* gc)
{
POINTER_SIZE_INT new_obj_occupied_size = 0;
lock(gc->mutator_list_lock);
Mutator* mutator = gc->mutator_list;
while (mutator) {
new_obj_occupied_size += mutator->new_obj_occupied_size;
mutator = mutator->next;
}
unlock(gc->mutator_list_lock);
return new_obj_occupied_size + desturcted_mutator_alloced_occupied_size;
}
unsigned int gc_reset_mutator_new_obj_size(GC * gc)
{
POINTER_SIZE_INT new_obj_occupied_size = 0;
lock(gc->mutator_list_lock);
Mutator* mutator = gc->mutator_list;
while (mutator) {
new_obj_occupied_size += mutator->new_obj_occupied_size;
mutator->new_obj_size = 0;
mutator->new_obj_num = 0;
mutator->new_obj_occupied_size = 0;
mutator->write_barrier_marked_size = 0;
mutator->dirty_obj_num = 0;
mutator = mutator->next;
}
new_obj_occupied_size += desturcted_mutator_alloced_occupied_size;
desturcted_mutator_alloced_size = 0;
desturcted_mutator_alloced_num = 0;
desturcted_mutator_alloced_occupied_size = 0;
unlock(gc->mutator_list_lock);
return new_obj_occupied_size;
}
unsigned int gc_get_mutator_number(GC *gc)
{
return gc->num_mutators;
}