Commit | Line | Data |
---|---|---|
353120b4 | 1 | // SPDX-License-Identifier: GPL-2.0 |
32c261c0 | 2 | #include <sys/mman.h> |
7728fa0c JO |
3 | #include <linux/ring_buffer.h> |
4 | #include <linux/perf_event.h> | |
5 | #include <perf/mmap.h> | |
353120b4 | 6 | #include <internal/mmap.h> |
bf59b305 | 7 | #include <internal/lib.h> |
80e53d11 | 8 | #include <linux/kernel.h> |
353120b4 | 9 | |
80e53d11 JO |
10 | void perf_mmap__init(struct perf_mmap *map, bool overwrite, |
11 | libperf_unmap_cb_t unmap_cb) | |
353120b4 JO |
12 | { |
13 | map->fd = -1; | |
14 | map->overwrite = overwrite; | |
80e53d11 | 15 | map->unmap_cb = unmap_cb; |
353120b4 JO |
16 | refcount_set(&map->refcnt, 0); |
17 | } | |
bf59b305 JO |
18 | |
19 | size_t perf_mmap__mmap_len(struct perf_mmap *map) | |
20 | { | |
21 | return map->mask + 1 + page_size; | |
22 | } | |
32c261c0 JO |
23 | |
24 | int perf_mmap__mmap(struct perf_mmap *map, struct perf_mmap_param *mp, | |
25 | int fd, int cpu) | |
26 | { | |
27 | map->prev = 0; | |
28 | map->mask = mp->mask; | |
29 | map->base = mmap(NULL, perf_mmap__mmap_len(map), mp->prot, | |
30 | MAP_SHARED, fd, 0); | |
31 | if (map->base == MAP_FAILED) { | |
32 | map->base = NULL; | |
33 | return -1; | |
34 | } | |
35 | ||
36 | map->fd = fd; | |
37 | map->cpu = cpu; | |
38 | return 0; | |
39 | } | |
e75710f0 | 40 | |
59d7ea62 JO |
41 | void perf_mmap__munmap(struct perf_mmap *map) |
42 | { | |
43 | if (map && map->base != NULL) { | |
44 | munmap(map->base, perf_mmap__mmap_len(map)); | |
45 | map->base = NULL; | |
46 | map->fd = -1; | |
47 | refcount_set(&map->refcnt, 0); | |
48 | } | |
80e53d11 JO |
49 | if (map && map->unmap_cb) |
50 | map->unmap_cb(map); | |
59d7ea62 JO |
51 | } |
52 | ||
e75710f0 JO |
53 | void perf_mmap__get(struct perf_mmap *map) |
54 | { | |
55 | refcount_inc(&map->refcnt); | |
56 | } | |
80e53d11 JO |
57 | |
58 | void perf_mmap__put(struct perf_mmap *map) | |
59 | { | |
60 | BUG_ON(map->base && refcount_read(&map->refcnt) == 0); | |
61 | ||
62 | if (refcount_dec_and_test(&map->refcnt)) | |
63 | perf_mmap__munmap(map); | |
64 | } | |
7728fa0c JO |
65 | |
66 | static inline void perf_mmap__write_tail(struct perf_mmap *md, u64 tail) | |
67 | { | |
68 | ring_buffer_write_tail(md->base, tail); | |
69 | } | |
70 | ||
71 | u64 perf_mmap__read_head(struct perf_mmap *map) | |
72 | { | |
73 | return ring_buffer_read_head(map->base); | |
74 | } | |
75 | ||
76 | static bool perf_mmap__empty(struct perf_mmap *map) | |
77 | { | |
78 | struct perf_event_mmap_page *pc = map->base; | |
79 | ||
80 | return perf_mmap__read_head(map) == map->prev && !pc->aux_size; | |
81 | } | |
82 | ||
83 | void perf_mmap__consume(struct perf_mmap *map) | |
84 | { | |
85 | if (!map->overwrite) { | |
86 | u64 old = map->prev; | |
87 | ||
88 | perf_mmap__write_tail(map, old); | |
89 | } | |
90 | ||
91 | if (refcount_read(&map->refcnt) == 1 && perf_mmap__empty(map)) | |
92 | perf_mmap__put(map); | |
93 | } |