Fix: perf counters: sign-extend pmc register
[lttng-ust.git] / liblttng-ust / lttng-context-perf-counters.c
index d6bd41cc9e20a170dc73f5d76d473781cdd1e737..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);
 
@@ -134,7 +140,7 @@ static
 struct perf_event_mmap_page *setup_perf(struct perf_event_attr *attr)
 {
        void *perf_addr;
-       int fd;
+       int fd, ret;
 
        fd = sys_perf_event_open(attr, 0, -1, -1, 0);
        if (fd < 0)
@@ -144,7 +150,10 @@ struct perf_event_mmap_page *setup_perf(struct perf_event_attr *attr)
                        PROT_READ, MAP_SHARED, fd, 0);
        if (perf_addr == MAP_FAILED)
                return NULL;
-       close(fd);
+       ret = close(fd);
+       if (ret) {
+               perror("Error closing LTTng-UST perf memory mapping FD");
+       }
        return perf_addr;
 }
 
@@ -277,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 */
@@ -399,6 +408,7 @@ int lttng_add_perf_counter_to_ctx(uint32_t type,
         * the field here.
         */
 
+       lttng_context_update(*ctx);
        return 0;
 
 setup_error:
This page took 0.025394 seconds and 4 git commands to generate.