]> gitweb.factorcode.org Git - factor.git/commitdiff
vm: sampling profiler timer for windows
authorJoe Groff <arcata@gmail.com>
Mon, 31 Oct 2011 21:38:49 +0000 (14:38 -0700)
committerJoe Groff <arcata@gmail.com>
Wed, 2 Nov 2011 20:23:11 +0000 (13:23 -0700)
Spawn a thread and have it spin on the performance counter, triggering safepoints on the main thread every sample time

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

index 1e587adc4c51e03ffff39ac34cd8eb7154346ba9..a5c066b8a208afbeefea7ed4a4afdd1273b989c8 100755 (executable)
@@ -170,18 +170,18 @@ void factor_vm::enqueue_safepoint_fep()
        code->guard_safepoint();
 }
 
-void factor_vm::enqueue_safepoint_sample(cell pc, bool foreign_thread_p)
+void factor_vm::enqueue_safepoint_sample(cell samples, cell pc, bool foreign_thread_p)
 {
-       if (sampling_profiler_p)
+       if (FACTOR_MEMORY_BARRIER(), sampling_profiler_p)
        {
-               FACTOR_ATOMIC_ADD(&safepoint_sample_count, 1);
+               FACTOR_ATOMIC_ADD(&safepoint_sample_count, samples);
                if (foreign_thread_p)
-                       FACTOR_ATOMIC_ADD(&safepoint_foreign_thread_sample_count, 1);
+                       FACTOR_ATOMIC_ADD(&safepoint_foreign_thread_sample_count, samples);
                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);
+                       if (FACTOR_MEMORY_BARRIER(), current_gc)
+                               FACTOR_ATOMIC_ADD(&safepoint_gc_sample_count, samples);
+                       if (pc != 0 && !code->seg->in_segment_p(pc))
+                               FACTOR_ATOMIC_ADD(&safepoint_foreign_sample_count, samples);
                }
                code->guard_safepoint();
        }
index f9065ac177995d331e750adac0ee4ecedb4142a5..4533741267822b73fd61a6e55dfc05051b318146 100755 (executable)
@@ -209,10 +209,10 @@ void sample_signal_handler(int signal, siginfo_t *siginfo, void *uap)
 {
        factor_vm *vm = current_vm_p();
        if (vm)
-               vm->enqueue_safepoint_sample((cell)UAP_PROGRAM_COUNTER(uap), false);
+               vm->enqueue_safepoint_sample(1, (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);
+               the_only_vm->enqueue_safepoint_sample(1, (cell)UAP_PROGRAM_COUNTER(uap), true);
        }
 }
 
index e220e11031d7da8b2cf1510a3984d5fd362f2a3a..937a2f7c40c691260976dbba7f10cf0951146084 100755 (executable)
@@ -301,14 +301,54 @@ void factor_vm::open_console()
        SetConsoleCtrlHandler(factor::ctrl_handler, TRUE);
 }
 
+void factor_vm::sampler_thread_loop()
+{
+       LARGE_INTEGER counter, new_counter, units_per_second;
+
+       assert(QueryPerformanceFrequency(&units_per_second));
+       long long units_per_sample =
+               units_per_second.QuadPart / FACTOR_PROFILE_SAMPLES_PER_SECOND;
+
+       assert(QueryPerformanceCounter(&counter));
+       while (FACTOR_MEMORY_BARRIER(), sampling_profiler_p)
+       {
+               Sleep(0);
+               assert(QueryPerformanceCounter(&new_counter));
+               cell samples = 0;
+               while (new_counter.QuadPart - counter.QuadPart > units_per_sample) {
+                       // We would have to suspend the thread to sample the PC
+                       ++samples;
+                       counter.QuadPart += units_per_sample;
+               }
+               enqueue_safepoint_sample(samples, 0, false);
+       }
+}
+
+static DWORD WINAPI sampler_thread_entry(LPVOID parent_vm)
+{
+       static_cast<factor_vm*>(parent_vm)->sampler_thread_loop();
+       return 0;
+}
+
 void factor_vm::start_sampling_profiler_timer()
 {
-       general_error(ERROR_NOT_IMPLEMENTED, false_object, false_object);
+       sampler_thread = CreateThread(
+               NULL,
+               0,
+               &sampler_thread_entry,
+               static_cast<LPVOID>(this),
+               0,
+               NULL
+       );
 }
 
 void factor_vm::end_sampling_profiler_timer()
 {
-       general_error(ERROR_NOT_IMPLEMENTED, false_object, false_object);
+       DWORD wait_result = WaitForSingleObject(sampler_thread,
+               3000/FACTOR_PROFILE_SAMPLES_PER_SECOND);
+       if (wait_result != WAIT_OBJECT_0)
+               TerminateThread(sampler_thread);
+       sampler_thread = NULL;
 }
 
 }
index 9eb69a34b19509750027b2c29f9f4e99220f1ce5..c7865b0a46721ff763ac2bbc59dda2096846a310 100644 (file)
@@ -101,9 +101,10 @@ void factor_vm::start_sampling_profiler()
 
 void factor_vm::end_sampling_profiler()
 {
+       sampling_profiler_p = false;
+       FACTOR_MEMORY_BARRIER();
        end_sampling_profiler_timer();
        record_sample();
-       sampling_profiler_p = false;
 }
 
 void factor_vm::primitive_sampling_profiler()
index 5ff86c0d9f34d08d5eb42d89a7b2c917cf43d9ea..9f07596da09fb5f83832218ad603a156056394a3 100755 (executable)
--- a/vm/vm.hpp
+++ b/vm/vm.hpp
@@ -62,7 +62,7 @@ struct factor_vm
 
        /* Is profiling enabled? */
        bool counting_profiler_p;
-       bool sampling_profiler_p;
+       volatile bool sampling_profiler_p;
 
        /* Global variables used to pass fault handler state from signal handler
        to VM */
@@ -93,7 +93,7 @@ struct factor_vm
        callback_heap *callbacks;
 
        /* Only set if we're performing a GC */
-       gc_state *current_gc;
+       volatile gc_state *current_gc;
 
        /* Mark stack */
        std::vector<cell> mark_stack;
@@ -216,7 +216,7 @@ struct factor_vm
        void synchronous_signal_handler_impl();
        void fp_signal_handler_impl();
        void enqueue_safepoint_fep();
-       void enqueue_safepoint_sample(cell pc, bool foreign_thread_p);
+       void enqueue_safepoint_sample(cell samples, cell pc, bool foreign_thread_p);
        void handle_safepoint();
 
        // bignum
@@ -727,6 +727,9 @@ struct factor_vm
 
        // os-windows
   #if defined(WINDOWS)
+       HANDLE sampler_thread;
+       void sampler_thread_loop();
+
        const vm_char *vm_executable_path();
        const vm_char *default_image_path();
        void windows_image_path(vm_char *full_path, vm_char *temp_path, unsigned int length);