vm: count samples from foreign threads

On OS X it appears the mach exception thread and libdispatch queue threads occasionally get the SIGALRM from the itimer. Count those as foreign_thread_samples instead of letting the signal kill the process.
db4
Joe Groff 2011-10-31 00:10:30 -07:00
parent 27d7e4af53
commit f5cdfaeb2a
6 changed files with 52 additions and 11 deletions

View File

@ -170,13 +170,19 @@ void factor_vm::enqueue_safepoint_fep()
code->guard_safepoint();
}
void factor_vm::enqueue_safepoint_sample()
void factor_vm::enqueue_safepoint_sample(cell pc, bool foreign_thread_p)
{
if (sampling_profiler_p)
{
FACTOR_ATOMIC_ADD(&safepoint_sample_count, 1);
if (current_gc)
FACTOR_ATOMIC_ADD(&safepoint_gc_sample_count, 1);
if (foreign_thread_p)
FACTOR_ATOMIC_ADD(&safepoint_foreign_thread_sample_count, 1);
else {
if (current_gc)
FACTOR_ATOMIC_ADD(&safepoint_gc_sample_count, 1);
if (!code->seg->in_segment_p(pc))
FACTOR_ATOMIC_ADD(&safepoint_foreign_sample_count, 1);
}
code->guard_safepoint();
}
}

View File

@ -209,9 +209,11 @@ void sample_signal_handler(int signal, siginfo_t *siginfo, void *uap)
{
factor_vm *vm = current_vm_p();
if (vm)
vm->enqueue_safepoint_sample();
else
fatal_error("Foreign thread received signal", signal);
vm->enqueue_safepoint_sample((cell)UAP_PROGRAM_COUNTER(uap), false);
else if (thread_vms.size() == 1) {
factor_vm *the_only_vm = thread_vms.begin()->second;
the_only_vm->enqueue_safepoint_sample((cell)UAP_PROGRAM_COUNTER(uap), true);
}
}
void ignore_signal_handler(int signal, siginfo_t *siginfo, void *uap)

View File

@ -6,10 +6,14 @@ namespace factor
profiling_sample::profiling_sample(factor_vm *vm,
cell sample_count,
cell gc_sample_count,
cell foreign_sample_count,
cell foreign_thread_sample_count,
context *ctx)
:
sample_count(sample_count),
gc_sample_count(gc_sample_count),
foreign_sample_count(foreign_sample_count),
foreign_thread_sample_count(foreign_thread_sample_count),
ctx(ctx)
{
vm->record_callstack_sample(&callstack_begin, &callstack_end);
@ -19,20 +23,33 @@ void factor_vm::record_sample()
{
cell recorded_sample_count;
cell recorded_gc_sample_count;
cell recorded_foreign_sample_count;
cell recorded_foreign_thread_sample_count;
FACTOR_MEMORY_BARRIER();
recorded_sample_count = safepoint_sample_count;
recorded_gc_sample_count = safepoint_gc_sample_count;
if (recorded_sample_count == 0 && recorded_gc_sample_count == 0)
recorded_foreign_sample_count = safepoint_foreign_sample_count;
recorded_foreign_thread_sample_count = safepoint_foreign_thread_sample_count;
if (recorded_sample_count
+ recorded_gc_sample_count
+ recorded_foreign_sample_count
+ recorded_foreign_thread_sample_count
== 0)
return;
/* Another sample signal could be raised while we record these counts */
FACTOR_ATOMIC_SUB(&safepoint_sample_count, recorded_sample_count);
FACTOR_ATOMIC_SUB(&safepoint_gc_sample_count, recorded_gc_sample_count);
FACTOR_ATOMIC_SUB(&safepoint_foreign_sample_count, recorded_foreign_sample_count);
FACTOR_ATOMIC_SUB(&safepoint_foreign_thread_sample_count, recorded_foreign_thread_sample_count);
samples.push_back(profiling_sample(
this,
recorded_sample_count,
recorded_gc_sample_count,
recorded_foreign_sample_count,
recorded_foreign_thread_sample_count,
ctx
));
}
@ -105,11 +122,13 @@ void factor_vm::primitive_get_samples()
for (; from_iter != samples.end(); ++from_iter, ++to_i)
{
data_root<array> sample(allot_array(4, false_object),this);
data_root<array> sample(allot_array(6, false_object),this);
set_array_nth(sample.untagged(),0,from_unsigned_cell(from_iter->sample_count));
set_array_nth(sample.untagged(),1,from_unsigned_cell(from_iter->gc_sample_count));
set_array_nth(sample.untagged(),2,allot_alien((void*)from_iter->ctx));
set_array_nth(sample.untagged(),2,from_unsigned_cell(from_iter->foreign_sample_count));
set_array_nth(sample.untagged(),3,from_unsigned_cell(from_iter->foreign_thread_sample_count));
set_array_nth(sample.untagged(),4,allot_alien((void*)from_iter->ctx));
cell callstack_size = from_iter->callstack_end - from_iter->callstack_begin;
data_root<array> callstack(allot_array(callstack_size,false_object),this);
@ -123,7 +142,7 @@ void factor_vm::primitive_get_samples()
for (; c_from_iter != c_from_iter_end; ++c_from_iter, ++c_to_i)
set_array_nth(callstack.untagged(),c_to_i,(*c_from_iter)->owner);
set_array_nth(sample.untagged(),3,callstack.value());
set_array_nth(sample.untagged(),5,callstack.value());
set_array_nth(samples_array.untagged(),to_i,sample.value());
}

View File

@ -9,6 +9,10 @@ struct profiling_sample
cell sample_count;
// Number of samples taken during GC
cell gc_sample_count;
// Number of samples taken during foreign code execution
cell foreign_sample_count;
// Number of samples taken during code execution in non-Factor threads
cell foreign_thread_sample_count;
// Active context during sample
context *ctx;
/* The callstack at safepoint time. Indexes to the beginning and ending
@ -18,6 +22,8 @@ struct profiling_sample
profiling_sample(factor_vm *vm,
cell sample_count,
cell gc_sample_count,
cell foreign_sample_count,
cell foreign_thread_sample_count,
context *ctx);
};

View File

@ -79,6 +79,9 @@ VM_C_API void *factor_memcpy(void *dst, void *src, size_t len);
#endif
#define FACTOR_MEMORY_BARRIER() \
MemoryBarrier()
#elif defined(__GNUC__) || defined(__clang__)
#define FACTOR_ATOMIC_CAS(ptr, old_val, new_val) \
@ -90,6 +93,9 @@ VM_C_API void *factor_memcpy(void *dst, void *src, size_t len);
#define FACTOR_ATOMIC_SUB(ptr, val) \
__sync_sub_and_fetch(ptr, val)
#define FACTOR_MEMORY_BARRIER() \
__sync_synchronize()
#else
#error "Unsupported compiler"
#endif

View File

@ -77,6 +77,8 @@ struct factor_vm
std::vector<code_block*> sample_callstacks;
volatile cell safepoint_sample_count;
volatile cell safepoint_gc_sample_count;
volatile cell safepoint_foreign_sample_count;
volatile cell safepoint_foreign_thread_sample_count;
/* GC is off during heap walking */
bool gc_off;
@ -214,7 +216,7 @@ struct factor_vm
void synchronous_signal_handler_impl();
void fp_signal_handler_impl();
void enqueue_safepoint_fep();
void enqueue_safepoint_sample();
void enqueue_safepoint_sample(cell pc, bool foreign_thread_p);
void handle_safepoint();
// bignum