Fix: perf counters: sign-extend pmc register
[lttng-ust.git] / liblttng-ust / lttng-context-perf-counters.c
index 83b371c5ba91431f47f44ce6880a4087d2e0244c..c3728867af8f018d202ea38e8f126b51bd8015ac 100644 (file)
@@ -69,7 +69,7 @@ struct lttng_perf_counter_field {
 static pthread_key_t perf_counter_key;
 
 static
-size_t perf_counter_get_size(size_t offset)
+size_t perf_counter_get_size(struct lttng_ctx_field *field, size_t offset)
 {
        size_t size = 0;
 
@@ -110,11 +110,17 @@ uint64_t read_perf_counter(struct perf_event_mmap_page *pc)
                cmm_barrier();
 
                idx = pc->index;
-               if (idx)
-                       count = pc->offset + rdpmc(idx - 1);
-               else
+               if (idx) {
+                       int64_t pmcval;
+
+                       pmcval = rdpmc(idx - 1);
+                       /* Sign-extend the pmc register result. */
+                       pmcval <<= 64 - pc->pmc_width;
+                       pmcval >>= 64 - pc->pmc_width;
+                       count = pc->offset + pmcval;
+               } else {
                        count = 0;
-
+               }
                cmm_barrier();
        } while (CMM_LOAD_SHARED(pc->lock) != seq);
 
@@ -280,12 +286,12 @@ void perf_counter_record(struct lttng_ctx_field *field,
 
 static
 void perf_counter_get_value(struct lttng_ctx_field *field,
-               union lttng_ctx_value *value)
+               struct lttng_ctx_value *value)
 {
        uint64_t v;
 
        v = wrapper_perf_counter_read(field);
-       value->s64 = v;
+       value->u.s64 = v;
 }
 
 /* Called with UST lock held */
This page took 0.023364 seconds and 4 git commands to generate.