Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

perf record: Introduce thread affinity and mmap masks

Introduce affinity and mmap thread masks. Thread affinity mask
defines CPUs that a thread is allowed to run on. Thread maps
mask defines mmap data buffers the thread serves to stream
profiling data from.

Reviewed-by: Riccardo Mancini <rickyman7@gmail.com>
Signed-off-by: Alexey Bayduraev <alexey.v.bayduraev@linux.intel.com>
Tested-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Riccardo Mancini <rickyman7@gmail.com>
Acked-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Namhyung Kim <namhyung@gmail.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Antonov <alexander.antonov@linux.intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexei Budankov <abudankov@huawei.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/9042bf7daf988e17e17e6acbf5d29590bde869cd.1642440724.git.alexey.v.bayduraev@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Alexey Bayduraev and committed by
Arnaldo Carvalho de Melo
7954f716 ea0ddc27

+123
+123
tools/perf/builtin-record.c
··· 87 87 int cur_file; 88 88 }; 89 89 90 + struct thread_mask { 91 + struct mmap_cpu_mask maps; 92 + struct mmap_cpu_mask affinity; 93 + }; 94 + 90 95 struct record { 91 96 struct perf_tool tool; 92 97 struct record_opts opts; ··· 117 112 struct mmap_cpu_mask affinity_mask; 118 113 unsigned long output_max_size; /* = 0: unlimited */ 119 114 struct perf_debuginfod debuginfod; 115 + int nr_threads; 116 + struct thread_mask *thread_masks; 120 117 }; 121 118 122 119 static volatile int done; ··· 2211 2204 return 0; 2212 2205 } 2213 2206 2207 + static int record__mmap_cpu_mask_alloc(struct mmap_cpu_mask *mask, int nr_bits) 2208 + { 2209 + mask->nbits = nr_bits; 2210 + mask->bits = bitmap_zalloc(mask->nbits); 2211 + if (!mask->bits) 2212 + return -ENOMEM; 2213 + 2214 + return 0; 2215 + } 2216 + 2217 + static void record__mmap_cpu_mask_free(struct mmap_cpu_mask *mask) 2218 + { 2219 + bitmap_free(mask->bits); 2220 + mask->nbits = 0; 2221 + } 2222 + 2223 + static int record__thread_mask_alloc(struct thread_mask *mask, int nr_bits) 2224 + { 2225 + int ret; 2226 + 2227 + ret = record__mmap_cpu_mask_alloc(&mask->maps, nr_bits); 2228 + if (ret) { 2229 + mask->affinity.bits = NULL; 2230 + return ret; 2231 + } 2232 + 2233 + ret = record__mmap_cpu_mask_alloc(&mask->affinity, nr_bits); 2234 + if (ret) { 2235 + record__mmap_cpu_mask_free(&mask->maps); 2236 + mask->maps.bits = NULL; 2237 + } 2238 + 2239 + return ret; 2240 + } 2241 + 2242 + static void record__thread_mask_free(struct thread_mask *mask) 2243 + { 2244 + record__mmap_cpu_mask_free(&mask->maps); 2245 + record__mmap_cpu_mask_free(&mask->affinity); 2246 + } 2247 + 2214 2248 static int parse_output_max_size(const struct option *opt, 2215 2249 const char *str, int unset) 2216 2250 { ··· 2731 2683 2732 2684 struct option *record_options = __record_options; 2733 2685 2686 + static void record__mmap_cpu_mask_init(struct mmap_cpu_mask *mask, struct perf_cpu_map *cpus) 2687 + { 2688 + int c; 2689 + 2690 + for (c = 0; c < cpus->nr; c++) 2691 + set_bit(cpus->map[c].cpu, mask->bits); 2692 + } 2693 + 2694 + static void record__free_thread_masks(struct record *rec, int nr_threads) 2695 + { 2696 + int t; 2697 + 2698 + if (rec->thread_masks) 2699 + for (t = 0; t < nr_threads; t++) 2700 + record__thread_mask_free(&rec->thread_masks[t]); 2701 + 2702 + zfree(&rec->thread_masks); 2703 + } 2704 + 2705 + static int record__alloc_thread_masks(struct record *rec, int nr_threads, int nr_bits) 2706 + { 2707 + int t, ret; 2708 + 2709 + rec->thread_masks = zalloc(nr_threads * sizeof(*(rec->thread_masks))); 2710 + if (!rec->thread_masks) { 2711 + pr_err("Failed to allocate thread masks\n"); 2712 + return -ENOMEM; 2713 + } 2714 + 2715 + for (t = 0; t < nr_threads; t++) { 2716 + ret = record__thread_mask_alloc(&rec->thread_masks[t], nr_bits); 2717 + if (ret) { 2718 + pr_err("Failed to allocate thread masks[%d]\n", t); 2719 + goto out_free; 2720 + } 2721 + } 2722 + 2723 + return 0; 2724 + 2725 + out_free: 2726 + record__free_thread_masks(rec, nr_threads); 2727 + 2728 + return ret; 2729 + } 2730 + 2731 + static int record__init_thread_default_masks(struct record *rec, struct perf_cpu_map *cpus) 2732 + { 2733 + int ret; 2734 + 2735 + ret = record__alloc_thread_masks(rec, 1, cpu__max_cpu().cpu); 2736 + if (ret) 2737 + return ret; 2738 + 2739 + record__mmap_cpu_mask_init(&rec->thread_masks->maps, cpus); 2740 + 2741 + rec->nr_threads = 1; 2742 + 2743 + return 0; 2744 + } 2745 + 2746 + static int record__init_thread_masks(struct record *rec) 2747 + { 2748 + struct perf_cpu_map *cpus = rec->evlist->core.cpus; 2749 + 2750 + return record__init_thread_default_masks(rec, cpus); 2751 + } 2752 + 2734 2753 int cmd_record(int argc, const char **argv) 2735 2754 { 2736 2755 int err; ··· 3063 2948 goto out; 3064 2949 } 3065 2950 2951 + err = record__init_thread_masks(rec); 2952 + if (err) { 2953 + pr_err("Failed to initialize parallel data streaming masks\n"); 2954 + goto out; 2955 + } 2956 + 3066 2957 if (rec->opts.nr_cblocks > nr_cblocks_max) 3067 2958 rec->opts.nr_cblocks = nr_cblocks_max; 3068 2959 pr_debug("nr_cblocks: %d\n", rec->opts.nr_cblocks); ··· 3087 2966 symbol__exit(); 3088 2967 auxtrace_record__free(rec->itr); 3089 2968 out_opts: 2969 + record__free_thread_masks(rec, rec->nr_threads); 2970 + rec->nr_threads = 0; 3090 2971 evlist__close_control(rec->opts.ctl_fd, rec->opts.ctl_fd_ack, &rec->opts.ctl_fd_close); 3091 2972 return err; 3092 2973 }