diff mbox

[FFmpeg-devel,3/3] lavu/timer.h: add Linux Perf API support

Message ID 20170902181740.23104-3-u@pkh.me
State Accepted
Commit f61379cbd45a91b26c7a1ddd3f16417466c435cd
Headers show

Commit Message

Clément Bœsch Sept. 2, 2017, 6:17 p.m. UTC
From: Clément Bœsch <cboesch@gopro.com>

Refer to "checkasm: use perf API on Linux ARM*" commit for the
rationale.

The implementation is somehow duplicated with checkasm, but so is the
current usage of AV_READ_TIME(). Until these implementations and
heuristics are made consistent, I don't see a way of sharing that code.

Note: when using libavutil/timer.h, it is now important to include
before any other include due to the _GNU_SOURCE requirement.
---
 libavutil/timer.h | 46 +++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 43 insertions(+), 3 deletions(-)

Comments

Michael Niedermayer Sept. 3, 2017, 6:30 p.m. UTC | #1
On Sat, Sep 02, 2017 at 08:17:40PM +0200, Clément Bœsch wrote:
> From: Clément Bœsch <cboesch@gopro.com>
> 
> Refer to "checkasm: use perf API on Linux ARM*" commit for the
> rationale.
> 
> The implementation is somehow duplicated with checkasm, but so is the
> current usage of AV_READ_TIME(). Until these implementations and
> heuristics are made consistent, I don't see a way of sharing that code.
> 
> Note: when using libavutil/timer.h, it is now important to include
> before any other include due to the _GNU_SOURCE requirement.
> ---
>  libavutil/timer.h | 46 +++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 43 insertions(+), 3 deletions(-)

this breaks building   testprogs on qemu arm:

src/libavutil/tests/base64.c: In function ‘main’:
src/libavutil/tests/base64.c:105:159: error: implicit declaration of function ‘syscall’ [-Werror=implicit-function-declaration]
cc1: some warnings being treated as errors
make: *** [libavutil/tests/base64.o] Error 1
make: *** Waiting for unfinished jobs....
src/libavutil/tests/adler32.c: In function ‘main’:
src/libavutil/tests/adler32.c:42:159: error: implicit declaration of function ‘syscall’ [-Werror=implicit-function-declaration]
cc1: some warnings being treated as errors
make: *** [libavutil/tests/adler32.o] Error 1
src/libavutil/tests/aes.c: In function ‘main’:
src/libavutil/tests/aes.c:94:163: error: implicit declaration of function ‘syscall’ [-Werror=implicit-function-declaration]
cc1: some warnings being treated as errors
make: *** [libavutil/tests/aes.o] Error 1
src/libavformat/utils.c: In function ‘avformat_transfer_internal_stream_timing_info’:
src/libavformat/utils.c:5537:5: warning: ‘codec’ is deprecated (declared at src/libavformat/avformat.h:893) [-Wdeprecated-declarations]
src/libavformat/utils.c:5538:5: warning: ‘codec’ is deprecated (declared at src/libavformat/avformat.h:893) [-Wdeprecated-declarations]


[...]
Carl Eugen Hoyos Jan. 20, 2018, 9:57 p.m. UTC | #2
2017-09-02 20:17 GMT+02:00 Clément Bœsch <u@pkh.me>:
> From: Clément Bœsch <cboesch@gopro.com>
>
> Refer to "checkasm: use perf API on Linux ARM*" commit for the
> rationale.
>
> The implementation is somehow duplicated with checkasm, but so is the
> current usage of AV_READ_TIME(). Until these implementations and
> heuristics are made consistent, I don't see a way of sharing that code.
>
> Note: when using libavutil/timer.h, it is now important to include
> before any other include due to the _GNU_SOURCE requirement.
> ---
>  libavutil/timer.h | 46 +++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 43 insertions(+), 3 deletions(-)
>
> diff --git a/libavutil/timer.h b/libavutil/timer.h
> index da0761b607..f7ab455df2 100644
> --- a/libavutil/timer.h
> +++ b/libavutil/timer.h
> @@ -26,12 +26,22 @@
>  #ifndef AVUTIL_TIMER_H
>  #define AVUTIL_TIMER_H
>
> +#include "config.h"
> +
> +#if CONFIG_LINUX_PERF
> +# ifndef _GNU_SOURCE
> +#  define _GNU_SOURCE
> +# endif
> +# include <unistd.h> // read(3)
> +# include <sys/ioctl.h>
> +# include <asm/unistd.h>
> +# include <linux/perf_event.h>

Not sure how relevant this is but this
patch broke compilation for Android 19
and earlier, still supported by ndk 16b.

Carl Eugen
diff mbox

Patch

diff --git a/libavutil/timer.h b/libavutil/timer.h
index da0761b607..f7ab455df2 100644
--- a/libavutil/timer.h
+++ b/libavutil/timer.h
@@ -26,12 +26,22 @@ 
 #ifndef AVUTIL_TIMER_H
 #define AVUTIL_TIMER_H
 
+#include "config.h"
+
+#if CONFIG_LINUX_PERF
+# ifndef _GNU_SOURCE
+#  define _GNU_SOURCE
+# endif
+# include <unistd.h> // read(3)
+# include <sys/ioctl.h>
+# include <asm/unistd.h>
+# include <linux/perf_event.h>
+#endif
+
 #include <stdlib.h>
 #include <stdint.h>
 #include <inttypes.h>
 
-#include "config.h"
-
 #if HAVE_MACH_MACH_TIME_H
 #include <mach/mach_time.h>
 #endif
@@ -85,7 +95,37 @@ 
         }                                                                 \
     }
 
-#ifdef AV_READ_TIME
+#if CONFIG_LINUX_PERF
+
+#define START_TIMER                                                         \
+    static int linux_perf_fd;                                               \
+    uint64_t tperf;                                                         \
+    if (!linux_perf_fd) {                                                   \
+        struct perf_event_attr attr = {                                     \
+            .type           = PERF_TYPE_HARDWARE,                           \
+            .size           = sizeof(struct perf_event_attr),               \
+            .config         = PERF_COUNT_HW_CPU_CYCLES,                     \
+            .disabled       = 1,                                            \
+            .exclude_kernel = 1,                                            \
+            .exclude_hv     = 1,                                            \
+        };                                                                  \
+        linux_perf_fd = syscall(__NR_perf_event_open, &attr,                \
+                                0, -1, -1, 0);                              \
+    }                                                                       \
+    if (linux_perf_fd == -1) {                                              \
+        av_log(NULL, AV_LOG_ERROR, "perf_event_open failed: %s\n",          \
+               av_err2str(AVERROR(errno)));                                 \
+    } else {                                                                \
+        ioctl(linux_perf_fd, PERF_EVENT_IOC_RESET, 0);                      \
+        ioctl(linux_perf_fd, PERF_EVENT_IOC_ENABLE, 0);                     \
+    }
+
+#define STOP_TIMER(id)                                                      \
+    ioctl(linux_perf_fd, PERF_EVENT_IOC_DISABLE, 0);                        \
+    read(linux_perf_fd, &tperf, sizeof(tperf));                             \
+    TIMER_REPORT(id, tperf)
+
+#elif defined(AV_READ_TIME)
 #define START_TIMER                             \
     uint64_t tend;                              \
     uint64_t tstart = AV_READ_TIME();           \