]> gitweb.factorcode.org Git - factor.git/commitdiff
vm: count samples from foreign threads
authorJoe Groff <arcata@gmail.com>
Mon, 31 Oct 2011 07:10:30 +0000 (00:10 -0700)
committerJoe Groff <arcata@gmail.com>
Wed, 2 Nov 2011 20:23:10 +0000 (13:23 -0700)
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.

vm/errors.cpp
vm/os-unix.cpp
vm/sampling_profiler.cpp
vm/sampling_profiler.hpp
vm/utilities.hpp
vm/vm.hpp

index 870f8519588368b8c9bb1ee79fa64cde5db47788..1e587adc4c51e03ffff39ac34cd8eb7154346ba9 100755 (executable)
@@ -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();
        }
 }
index 28c697f575758976ef05ddf8ea668af99f0598b5..f9065ac177995d331e750adac0ee4ecedb4142a5 100755 (executable)
@@ -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)
index 4fd1d67d5f5e5bf08d41afdb59d9a03c0a19b723..9eb69a34b19509750027b2c29f9f4e99220f1ce5 100644 (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());
                }
index 86c3d3cc849a7e7c9fb00cfdbf8f888d86363179..939f74b186b4a54e67e581446735e04b4c8bc71c 100644 (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);
 };
 
index 2b93a62fbcf8baa3f64e0c4f2ee0b4bec47ef4f5..aa67a646e6a068a7129774e539bbe435f3bdf4aa 100755 (executable)
@@ -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
index b3feeb64891e0ac60d90a2507def940138a225f7..5ff86c0d9f34d08d5eb42d89a7b2c917cf43d9ea 100755 (executable)
--- a/vm/vm.hpp
+++ b/vm/vm.hpp
@@ -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